mirror of
https://github.com/harness/drone.git
synced 2025-05-21 19:39:59 +08:00
feat: [CDE-508]: add image auth (#3053)
* add comment * split pull image func into smaller parts * split pull image func into smaller parts * use MaskSecret type * fix lint * add image auth * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-image-auth * add image auth
This commit is contained in:
parent
dbe74b149d
commit
3b2db60eea
@ -16,6 +16,7 @@ package container
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -32,6 +33,7 @@ import (
|
|||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/image"
|
"github.com/docker/docker/api/types/image"
|
||||||
"github.com/docker/docker/api/types/mount"
|
"github.com/docker/docker/api/types/mount"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/api/types/strslice"
|
"github.com/docker/docker/api/types/strslice"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
@ -304,6 +306,7 @@ func PullImage(
|
|||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
runArgsMap map[types.RunArg]*types.RunArgValue,
|
runArgsMap map[types.RunArg]*types.RunArgValue,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
dockerRegistryAuth gitspaceTypes.DockerRegistryAuth,
|
||||||
) error {
|
) error {
|
||||||
imagePullRunArg := getImagePullPolicy(runArgsMap)
|
imagePullRunArg := getImagePullPolicy(runArgsMap)
|
||||||
gitspaceLogger.Info("Image pull policy is: " + imagePullRunArg)
|
gitspaceLogger.Info("Image pull policy is: " + imagePullRunArg)
|
||||||
@ -312,26 +315,28 @@ func PullImage(
|
|||||||
}
|
}
|
||||||
if imagePullRunArg == "missing" {
|
if imagePullRunArg == "missing" {
|
||||||
gitspaceLogger.Info("Checking if image " + imageName + " is present locally")
|
gitspaceLogger.Info("Checking if image " + imageName + " is present locally")
|
||||||
|
ok, err := isImagePresentLocally(ctx, imageName, dockerClient)
|
||||||
filterArgs := filters.NewArgs()
|
|
||||||
filterArgs.Add("reference", imageName)
|
|
||||||
|
|
||||||
images, err := dockerClient.ImageList(ctx, image.ListOptions{Filters: filterArgs})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gitspaceLogger.Error("Error listing images locally", err)
|
gitspaceLogger.Error("Error listing images locally", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(images) > 0 {
|
if ok {
|
||||||
gitspaceLogger.Info("Image " + imageName + " is present locally")
|
gitspaceLogger.Info("Image " + imageName + " is present locally")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gitspaceLogger.Info("Image " + imageName + " is not present locally")
|
gitspaceLogger.Info("Image " + imageName + " is not present locally")
|
||||||
}
|
}
|
||||||
|
|
||||||
gitspaceLogger.Info("Pulling image: " + imageName)
|
gitspaceLogger.Info("Pulling image: " + imageName)
|
||||||
|
|
||||||
pullResponse, err := dockerClient.ImagePull(ctx, imageName, image.PullOptions{Platform: getPlatform(runArgsMap)})
|
pullOpts, err := buildImagePullOptions(getPlatform(runArgsMap), dockerRegistryAuth)
|
||||||
|
if err != nil {
|
||||||
|
return logStreamWrapError(gitspaceLogger, "Error building image pull options", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pullResponse, err := dockerClient.ImagePull(ctx, imageName, pullOpts)
|
||||||
defer func() {
|
defer func() {
|
||||||
if pullResponse == nil {
|
if pullResponse == nil {
|
||||||
return
|
return
|
||||||
@ -382,6 +387,40 @@ func PullImage(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isImagePresentLocally(ctx context.Context, imageName string, dockerClient *client.Client) (bool, error) {
|
||||||
|
filterArgs := filters.NewArgs()
|
||||||
|
filterArgs.Add("reference", imageName)
|
||||||
|
|
||||||
|
images, err := dockerClient.ImageList(ctx, image.ListOptions{Filters: filterArgs})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(images) > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildImagePullOptions(
|
||||||
|
platform string,
|
||||||
|
dockerRegistryAuth gitspaceTypes.DockerRegistryAuth,
|
||||||
|
) (image.PullOptions, error) {
|
||||||
|
pullOpts := image.PullOptions{Platform: platform}
|
||||||
|
if dockerRegistryAuth.RegistryURL != "" {
|
||||||
|
authConfig := registry.AuthConfig{
|
||||||
|
Username: dockerRegistryAuth.Username.Value(),
|
||||||
|
Password: dockerRegistryAuth.Password.Value(),
|
||||||
|
ServerAddress: dockerRegistryAuth.RegistryURL,
|
||||||
|
}
|
||||||
|
auth, err := encodeAuthToBase64(authConfig)
|
||||||
|
if err != nil {
|
||||||
|
return image.PullOptions{}, fmt.Errorf("encoding auth for docker registry: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pullOpts.RegistryAuth = auth
|
||||||
|
}
|
||||||
|
|
||||||
|
return pullOpts, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ExtractRunArgsWithLogging(
|
func ExtractRunArgsWithLogging(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
spaceID int64,
|
spaceID int64,
|
||||||
@ -404,7 +443,7 @@ func ExtractRunArgsWithLogging(
|
|||||||
return runArgsMap, nil
|
return runArgsMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getContainerResponse retrieves container information and prepares the start response.
|
// GetContainerResponse retrieves container information and prepares the start response.
|
||||||
func GetContainerResponse(
|
func GetContainerResponse(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
dockerClient *client.Client,
|
dockerClient *client.Client,
|
||||||
@ -423,3 +462,12 @@ func GetContainerResponse(
|
|||||||
AbsoluteRepoPath: codeRepoDir,
|
AbsoluteRepoPath: codeRepoDir,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to encode the AuthConfig into a Base64 string.
|
||||||
|
func encodeAuthToBase64(authConfig registry.AuthConfig) (string, error) {
|
||||||
|
authJSON, err := json.Marshal(authConfig)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("encoding auth config: %w", err)
|
||||||
|
}
|
||||||
|
return base64.URLEncoding.EncodeToString(authJSON), nil
|
||||||
|
}
|
||||||
|
@ -114,6 +114,9 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
|
|||||||
}
|
}
|
||||||
defer e.closeDockerClient(dockerClient)
|
defer e.closeDockerClient(dockerClient)
|
||||||
|
|
||||||
|
// todo : update the code when private repository integration is supported in gitness
|
||||||
|
dockerRegistryAuth := gitspaceTypes.DockerRegistryAuth{}
|
||||||
|
|
||||||
// Step 3: Check the current state of the container
|
// Step 3: Check the current state of the container
|
||||||
state, err := e.checkContainerState(ctx, dockerClient, containerName)
|
state, err := e.checkContainerState(ctx, dockerClient, containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -144,7 +147,8 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
|
|||||||
resolvedRepoDetails,
|
resolvedRepoDetails,
|
||||||
infra,
|
infra,
|
||||||
defaultBaseImage,
|
defaultBaseImage,
|
||||||
ideService); err != nil {
|
ideService,
|
||||||
|
dockerRegistryAuth); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case ContainerStatePaused, ContainerStateCreated, ContainerStateUnknown, ContainerStateDead:
|
case ContainerStatePaused, ContainerStateCreated, ContainerStateUnknown, ContainerStateDead:
|
||||||
@ -369,6 +373,7 @@ func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
|||||||
resolvedRepoDetails scm.ResolvedDetails,
|
resolvedRepoDetails scm.ResolvedDetails,
|
||||||
defaultBaseImage string,
|
defaultBaseImage string,
|
||||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||||
|
dockerRegistryAuth gitspaceTypes.DockerRegistryAuth,
|
||||||
) error {
|
) error {
|
||||||
homeDir := GetUserHomeDir(gitspaceConfig.GitspaceUser.Identifier)
|
homeDir := GetUserHomeDir(gitspaceConfig.GitspaceUser.Identifier)
|
||||||
containerName := GetGitspaceContainerName(gitspaceConfig)
|
containerName := GetGitspaceContainerName(gitspaceConfig)
|
||||||
@ -386,7 +391,7 @@ func (e *EmbeddedDockerOrchestrator) runGitspaceSetupSteps(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pull the required image
|
// Pull the required image
|
||||||
if err := PullImage(ctx, imageName, dockerClient, runArgsMap, gitspaceLogger); err != nil {
|
if err := PullImage(ctx, imageName, dockerClient, runArgsMap, gitspaceLogger, dockerRegistryAuth); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
portMappings := infrastructure.GitspacePortMappings
|
portMappings := infrastructure.GitspacePortMappings
|
||||||
@ -665,6 +670,7 @@ func (e *EmbeddedDockerOrchestrator) createAndStartNewGitspace(
|
|||||||
infrastructure types.Infrastructure,
|
infrastructure types.Infrastructure,
|
||||||
defaultBaseImage string,
|
defaultBaseImage string,
|
||||||
ideService ide.IDE,
|
ideService ide.IDE,
|
||||||
|
dockerRegistryAuth gitspaceTypes.DockerRegistryAuth,
|
||||||
) error {
|
) error {
|
||||||
logStreamInstance, err := e.statefulLogger.CreateLogStream(ctx, gitspaceConfig.ID)
|
logStreamInstance, err := e.statefulLogger.CreateLogStream(ctx, gitspaceConfig.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -681,6 +687,7 @@ func (e *EmbeddedDockerOrchestrator) createAndStartNewGitspace(
|
|||||||
resolvedRepoDetails,
|
resolvedRepoDetails,
|
||||||
defaultBaseImage,
|
defaultBaseImage,
|
||||||
logStreamInstance,
|
logStreamInstance,
|
||||||
|
dockerRegistryAuth,
|
||||||
)
|
)
|
||||||
if startErr != nil {
|
if startErr != nil {
|
||||||
return fmt.Errorf("failed to start gitspace %s: %w", gitspaceConfig.Identifier, startErr)
|
return fmt.Errorf("failed to start gitspace %s: %w", gitspaceConfig.Identifier, startErr)
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
@ -38,3 +39,11 @@ type Step struct {
|
|||||||
type ZerologAdapter struct {
|
type ZerologAdapter struct {
|
||||||
logger *zerolog.Logger
|
logger *zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DockerRegistryAuth struct {
|
||||||
|
// only host name is required
|
||||||
|
// eg: docker.io instead of https://docker.io
|
||||||
|
RegistryURL string
|
||||||
|
Username *types.MaskSecret
|
||||||
|
Password *types.MaskSecret
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user