mirror of
https://github.com/fluxcd/flux2.git
synced 2025-11-02 18:58:33 +08:00
feat: enable bootstrap with custom CA locally
When a user provided the `--ca-file` flag to the `bootstrap` command, the given CA file wasn't taken into account for cloning the repository locally. It was just passed along to the CR that is created so Flux can make use of it when cloning the repository in-cluster. However, users may not want to add a custom CA to their local host's trust chain and may expect the `--ca-file` flag to be respected also for cloning the repository locally. This is what this commit accomplishes. closes #1775 Signed-off-by: Max Jonas Werner <mail@makk.es>
This commit is contained in:
@ -19,6 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -199,6 +200,15 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var caBundle []byte
|
||||||
|
if bootstrapArgs.caFile != "" {
|
||||||
|
var err error
|
||||||
|
caBundle, err = ioutil.ReadFile(bootstrapArgs.caFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Bootstrap config
|
// Bootstrap config
|
||||||
bootstrapOpts := []bootstrap.GitOption{
|
bootstrapOpts := []bootstrap.GitOption{
|
||||||
bootstrap.WithRepositoryURL(gitArgs.url),
|
bootstrap.WithRepositoryURL(gitArgs.url),
|
||||||
@ -208,6 +218,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
bootstrap.WithKubeconfig(rootArgs.kubeconfig, rootArgs.kubecontext),
|
bootstrap.WithKubeconfig(rootArgs.kubeconfig, rootArgs.kubecontext),
|
||||||
bootstrap.WithPostGenerateSecretFunc(promptPublicKey),
|
bootstrap.WithPostGenerateSecretFunc(promptPublicKey),
|
||||||
bootstrap.WithLogger(logger),
|
bootstrap.WithLogger(logger),
|
||||||
|
bootstrap.WithCABundle(caBundle),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup bootstrapper with constructed configs
|
// Setup bootstrapper with constructed configs
|
||||||
|
|||||||
@ -47,7 +47,7 @@ type Reconciler interface {
|
|||||||
// manifests with the provided values, committing them to Git and
|
// manifests with the provided values, committing them to Git and
|
||||||
// pushing to remote if there are any changes, and applying them
|
// pushing to remote if there are any changes, and applying them
|
||||||
// to the cluster.
|
// to the cluster.
|
||||||
ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options) error
|
ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options, secretOpts sourcesecret.Options) error
|
||||||
|
|
||||||
// ReconcileSourceSecret reconciles the source secret by generating
|
// ReconcileSourceSecret reconciles the source secret by generating
|
||||||
// a new secret with the provided values if the secret does not
|
// a new secret with the provided values if the secret does not
|
||||||
@ -87,7 +87,7 @@ func Run(ctx context.Context, reconciler Reconciler, manifestsBase string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := reconciler.ReconcileComponents(ctx, manifestsBase, installOpts); err != nil {
|
if err := reconciler.ReconcileComponents(ctx, manifestsBase, installOpts, secretOpts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := reconciler.ReconcileSourceSecret(ctx, secretOpts); err != nil {
|
if err := reconciler.ReconcileSourceSecret(ctx, secretOpts); err != nil {
|
||||||
|
|||||||
@ -46,8 +46,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type PlainGitBootstrapper struct {
|
type PlainGitBootstrapper struct {
|
||||||
url string
|
url string
|
||||||
branch string
|
branch string
|
||||||
|
caBundle []byte
|
||||||
|
|
||||||
author git.Author
|
author git.Author
|
||||||
commitMessageAppendix string
|
commitMessageAppendix string
|
||||||
@ -70,6 +71,16 @@ func WithRepositoryURL(url string) GitOption {
|
|||||||
return repositoryURLOption(url)
|
return repositoryURLOption(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithCABundle(b []byte) GitOption {
|
||||||
|
return caBundleOption(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type caBundleOption []byte
|
||||||
|
|
||||||
|
func (o caBundleOption) applyGit(b *PlainGitBootstrapper) {
|
||||||
|
b.caBundle = o
|
||||||
|
}
|
||||||
|
|
||||||
type repositoryURLOption string
|
type repositoryURLOption string
|
||||||
|
|
||||||
func (o repositoryURLOption) applyGit(b *PlainGitBootstrapper) {
|
func (o repositoryURLOption) applyGit(b *PlainGitBootstrapper) {
|
||||||
@ -97,7 +108,7 @@ func NewPlainGitProvider(git git.Git, kube client.Client, opts ...GitOption) (*P
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options) error {
|
func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options, secretOpts sourcesecret.Options) error {
|
||||||
// Clone if not already
|
// Clone if not already
|
||||||
if _, err := b.git.Status(); err != nil {
|
if _, err := b.git.Status(); err != nil {
|
||||||
if err != git.ErrNoGitRepository {
|
if err != git.ErrNoGitRepository {
|
||||||
@ -107,7 +118,7 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
|||||||
b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
|
b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
|
||||||
var cloned bool
|
var cloned bool
|
||||||
if err = retry(1, 2*time.Second, func() (err error) {
|
if err = retry(1, 2*time.Second, func() (err error) {
|
||||||
cloned, err = b.git.Clone(ctx, b.url, b.branch)
|
cloned, err = b.git.Clone(ctx, b.url, b.branch, b.caBundle)
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("failed to clone repository: %w", err)
|
return fmt.Errorf("failed to clone repository: %w", err)
|
||||||
@ -145,7 +156,7 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
|
b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
|
||||||
b.logger.Actionf("pushing component manifests to %q", b.url)
|
b.logger.Actionf("pushing component manifests to %q", b.url)
|
||||||
if err = b.git.Push(ctx); err != nil {
|
if err = b.git.Push(ctx, b.caBundle); err != nil {
|
||||||
return fmt.Errorf("failed to push manifests: %w", err)
|
return fmt.Errorf("failed to push manifests: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -260,7 +271,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
|||||||
b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
|
b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
|
||||||
var cloned bool
|
var cloned bool
|
||||||
if err = retry(1, 2*time.Second, func() (err error) {
|
if err = retry(1, 2*time.Second, func() (err error) {
|
||||||
cloned, err = b.git.Clone(ctx, b.url, b.branch)
|
cloned, err = b.git.Clone(ctx, b.url, b.branch, b.caBundle)
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("failed to clone repository: %w", err)
|
return fmt.Errorf("failed to clone repository: %w", err)
|
||||||
@ -309,7 +320,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
|
b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
|
||||||
b.logger.Actionf("pushing sync manifests to %q", b.url)
|
b.logger.Actionf("pushing sync manifests to %q", b.url)
|
||||||
if err = b.git.Push(ctx); err != nil {
|
if err = b.git.Push(ctx, b.caBundle); err != nil {
|
||||||
return fmt.Errorf("failed to push sync manifests: %w", err)
|
return fmt.Errorf("failed to push sync manifests: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -42,10 +42,10 @@ type Commit struct {
|
|||||||
// remote repository.
|
// remote repository.
|
||||||
type Git interface {
|
type Git interface {
|
||||||
Init(url, branch string) (bool, error)
|
Init(url, branch string) (bool, error)
|
||||||
Clone(ctx context.Context, url, branch string) (bool, error)
|
Clone(ctx context.Context, url, branch string, caBundle []byte) (bool, error)
|
||||||
Write(path string, reader io.Reader) error
|
Write(path string, reader io.Reader) error
|
||||||
Commit(message Commit) (string, error)
|
Commit(message Commit) (string, error)
|
||||||
Push(ctx context.Context) error
|
Push(ctx context.Context, caBundle []byte) error
|
||||||
Status() (bool, error)
|
Status() (bool, error)
|
||||||
Head() (string, error)
|
Head() (string, error)
|
||||||
Path() string
|
Path() string
|
||||||
|
|||||||
@ -82,7 +82,7 @@ func (g *GoGit) Init(url, branch string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GoGit) Clone(ctx context.Context, url, branch string) (bool, error) {
|
func (g *GoGit) Clone(ctx context.Context, url, branch string, caBundle []byte) (bool, error) {
|
||||||
branchRef := plumbing.NewBranchReferenceName(branch)
|
branchRef := plumbing.NewBranchReferenceName(branch)
|
||||||
r, err := gogit.PlainCloneContext(ctx, g.path, false, &gogit.CloneOptions{
|
r, err := gogit.PlainCloneContext(ctx, g.path, false, &gogit.CloneOptions{
|
||||||
URL: url,
|
URL: url,
|
||||||
@ -94,6 +94,7 @@ func (g *GoGit) Clone(ctx context.Context, url, branch string) (bool, error) {
|
|||||||
NoCheckout: false,
|
NoCheckout: false,
|
||||||
Progress: nil,
|
Progress: nil,
|
||||||
Tags: gogit.NoTags,
|
Tags: gogit.NoTags,
|
||||||
|
CABundle: caBundle,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == transport.ErrEmptyRemoteRepository || isRemoteBranchNotFoundErr(err, branchRef.String()) {
|
if err == transport.ErrEmptyRemoteRepository || isRemoteBranchNotFoundErr(err, branchRef.String()) {
|
||||||
@ -185,7 +186,7 @@ func (g *GoGit) Commit(message git.Commit) (string, error) {
|
|||||||
return commit.String(), nil
|
return commit.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GoGit) Push(ctx context.Context) error {
|
func (g *GoGit) Push(ctx context.Context, caBundle []byte) error {
|
||||||
if g.repository == nil {
|
if g.repository == nil {
|
||||||
return git.ErrNoGitRepository
|
return git.ErrNoGitRepository
|
||||||
}
|
}
|
||||||
@ -194,6 +195,7 @@ func (g *GoGit) Push(ctx context.Context) error {
|
|||||||
RemoteName: gogit.DefaultRemoteName,
|
RemoteName: gogit.DefaultRemoteName,
|
||||||
Auth: g.auth,
|
Auth: g.auth,
|
||||||
Progress: nil,
|
Progress: nil,
|
||||||
|
CABundle: caBundle,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user