1
0
mirror of synced 2026-03-01 11:16:56 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
Michael Bridgen
84e2cb4c1f Merge pull request #788 from fluxcd/create-secret-tls
Create secret for TLS command
2021-01-26 17:33:50 +00:00
Michael Bridgen
263c664acd Factor out more common secrets command code
Making the secret without data is always the same, so factor that out.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-26 17:25:33 +00:00
Michael Bridgen
b12c4c22fb Add command for creating TLS secrets
The image-reflector controller now accepts a secret containing a
client certificate and key, and/or a CA certificate; so it's useful to
have a command for creating them.

`flux create secret helm` is close, but accepts username/password
(which would be ignored), and has the wrong name of course. Happily
though, much can be shared between the implementations.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-01-26 17:25:33 +00:00
Stefan Prodan
9f39fadb9e Merge pull request #787 from fluxcd/fix-rbac-namespace
RBAC Fix: Replace SA namespace in ClusterRoleBindings
2021-01-26 19:21:19 +02:00
Stefan Prodan
4c29a1ca27 Replace SA namespace in RBAC
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-01-26 18:57:36 +02:00
Stefan Prodan
f4db124d50 Merge pull request #783 from fluxcd/rbac-fix
RBAC Fix: Add SA namespace to cluster role bindings
2021-01-26 16:24:16 +02:00
Stefan Prodan
8f8c7cccc6 Add SA namespace to RBAC
Fix flux install when not all controllers have been selected

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-01-26 16:16:34 +02:00
Hidde Beydals
e2097c28bd Merge pull request #782 from fluxcd/docs-img-auto-links
docs: fix image automation menu links
2021-01-26 14:34:29 +01:00
Hidde Beydals
871eb444fc docs: fix image automation menu links
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-01-26 14:26:18 +01:00
12 changed files with 241 additions and 62 deletions

View File

@@ -39,6 +39,21 @@ func init() {
createCmd.AddCommand(createSecretCmd)
}
func makeSecret(name string) (corev1.Secret, error) {
secretLabels, err := parseLabels()
if err != nil {
return corev1.Secret{}, err
}
return corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: rootArgs.namespace,
Labels: secretLabels,
},
}, nil
}
func upsertSecret(ctx context.Context, kubeClient client.Client, secret corev1.Secret) error {
namespacedName := types.NamespacedName{
Namespace: secret.GetNamespace(),

View File

@@ -24,8 +24,6 @@ import (
"time"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fluxcd/flux2/internal/flags"
"github.com/fluxcd/flux2/internal/utils"
@@ -106,6 +104,10 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("secret name is required")
}
name := args[0]
secret, err := makeSecret(name)
if err != nil {
return err
}
if secretGitArgs.url == "" {
return fmt.Errorf("url is required")
@@ -116,22 +118,9 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("git URL parse failed: %w", err)
}
secretLabels, err := parseLabels()
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: rootArgs.namespace,
Labels: secretLabels,
},
}
switch u.Scheme {
case "ssh":
pair, err := generateKeyPair(ctx, secretGitArgs.keyAlgorithm, secretGitArgs.rsaBits, secretGitArgs.ecdsaCurve)

View File

@@ -19,11 +19,8 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fluxcd/flux2/internal/utils"
)
@@ -58,9 +55,7 @@ The create secret helm command generates a Kubernetes secret with basic authenti
type secretHelmFlags struct {
username string
password string
certFile string
keyFile string
caFile string
secretTLSFlags
}
var secretHelmArgs secretHelmFlags
@@ -68,10 +63,7 @@ var secretHelmArgs secretHelmFlags
func init() {
createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.username, "username", "u", "", "basic authentication username")
createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.password, "password", "p", "", "basic authentication password")
createSecretHelmCmd.Flags().StringVar(&secretHelmArgs.certFile, "cert-file", "", "TLS authentication cert file path")
createSecretHelmCmd.Flags().StringVar(&secretHelmArgs.keyFile, "key-file", "", "TLS authentication key file path")
createSecretHelmCmd.Flags().StringVar(&secretHelmArgs.caFile, "ca-file", "", "TLS authentication CA file path")
initSecretTLSFlags(createSecretHelmCmd.Flags(), &secretHelmArgs.secretTLSFlags)
createSecretCmd.AddCommand(createSecretHelmCmd)
}
@@ -80,46 +72,18 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("secret name is required")
}
name := args[0]
secretLabels, err := parseLabels()
secret, err := makeSecret(name)
if err != nil {
return err
}
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: rootArgs.namespace,
Labels: secretLabels,
},
StringData: map[string]string{},
}
if secretHelmArgs.username != "" && secretHelmArgs.password != "" {
secret.StringData["username"] = secretHelmArgs.username
secret.StringData["password"] = secretHelmArgs.password
}
if secretHelmArgs.certFile != "" && secretHelmArgs.keyFile != "" {
cert, err := ioutil.ReadFile(secretHelmArgs.certFile)
if err != nil {
return fmt.Errorf("failed to read repository cert file '%s': %w", secretHelmArgs.certFile, err)
}
secret.StringData["certFile"] = string(cert)
key, err := ioutil.ReadFile(secretHelmArgs.keyFile)
if err != nil {
return fmt.Errorf("failed to read repository key file '%s': %w", secretHelmArgs.keyFile, err)
}
secret.StringData["keyFile"] = string(key)
}
if secretHelmArgs.caFile != "" {
ca, err := ioutil.ReadFile(secretHelmArgs.caFile)
if err != nil {
return fmt.Errorf("failed to read repository CA file '%s': %w", secretHelmArgs.caFile, err)
}
secret.StringData["caFile"] = string(ca)
if err = populateSecretTLS(&secret, secretHelmArgs.secretTLSFlags); err != nil {
return err
}
if createArgs.export {

View File

@@ -0,0 +1,128 @@
/*
Copyright 2020, 2021 The Flux authors
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 (
"context"
"fmt"
"io/ioutil"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
corev1 "k8s.io/api/core/v1"
"github.com/fluxcd/flux2/internal/utils"
)
var createSecretTLSCmd = &cobra.Command{
Use: "tls [name]",
Short: "Create or update a Kubernetes secret with TLS certificates",
Long: `
The create secret tls command generates a Kubernetes secret with certificates for use with TLS.`,
Example: `
# Create a TLS secret on disk and encrypt it with Mozilla SOPS.
# Files are expected to be PEM-encoded.
flux create secret tls certs \
--namespace=my-namespace \
--cert-file=./client.crt \
--key-file=./client.key \
--export > certs.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place certs.yaml
`,
RunE: createSecretTLSCmdRun,
}
type secretTLSFlags struct {
certFile string
keyFile string
caFile string
}
var secretTLSArgs secretTLSFlags
func initSecretTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) {
flags.StringVar(&args.certFile, "cert-file", "", "TLS authentication cert file path")
flags.StringVar(&args.keyFile, "key-file", "", "TLS authentication key file path")
flags.StringVar(&args.caFile, "ca-file", "", "TLS authentication CA file path")
}
func init() {
flags := createSecretTLSCmd.Flags()
initSecretTLSFlags(flags, &secretTLSArgs)
createSecretCmd.AddCommand(createSecretTLSCmd)
}
func populateSecretTLS(secret *corev1.Secret, args secretTLSFlags) error {
if args.certFile != "" && args.keyFile != "" {
cert, err := ioutil.ReadFile(args.certFile)
if err != nil {
return fmt.Errorf("failed to read repository cert file '%s': %w", args.certFile, err)
}
secret.StringData["certFile"] = string(cert)
key, err := ioutil.ReadFile(args.keyFile)
if err != nil {
return fmt.Errorf("failed to read repository key file '%s': %w", args.keyFile, err)
}
secret.StringData["keyFile"] = string(key)
}
if args.caFile != "" {
ca, err := ioutil.ReadFile(args.caFile)
if err != nil {
return fmt.Errorf("failed to read repository CA file '%s': %w", args.caFile, err)
}
secret.StringData["caFile"] = string(ca)
}
return nil
}
func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("secret name is required")
}
name := args[0]
secret, err := makeSecret(name)
if err != nil {
return err
}
if err = populateSecretTLS(&secret, secretTLSArgs); err != nil {
return err
}
if createArgs.export {
return exportSecret(secret)
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err
}
logger.Actionf("secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil
}

View File

@@ -30,4 +30,5 @@ The create source sub-commands generate Kubernetes secrets specific to Flux.
* [flux create](flux_create.md) - Create or update sources and resources
* [flux create secret git](flux_create_secret_git.md) - Create or update a Kubernetes secret for Git authentication
* [flux create secret helm](flux_create_secret_helm.md) - Create or update a Kubernetes secret for Helm repository authentication
* [flux create secret tls](flux_create_secret_tls.md) - Create or update a Kubernetes secret with TLS certificates

View File

@@ -0,0 +1,56 @@
## flux create secret tls
Create or update a Kubernetes secret with TLS certificates
### Synopsis
The create secret tls command generates a Kubernetes secret with certificates for use with TLS.
```
flux create secret tls [name] [flags]
```
### Examples
```
# Create a TLS secret on disk and encrypt it with Mozilla SOPS.
# Files are expected to be PEM-encoded.
flux create secret tls certs \
--namespace=my-namespace \
--cert-file=./client.crt \
--key-file=./client.key \
--export > certs.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place certs.yaml
```
### Options
```
--ca-file string TLS authentication CA file path
--cert-file string TLS authentication cert file path
-h, --help help for tls
--key-file string TLS authentication key file path
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--export export in YAML format to stdout
--interval duration source sync interval (default 1m0s)
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
--label strings set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux create secret](flux_create_secret.md) - Create or update Kubernetes secrets

1
go.mod
View File

@@ -20,6 +20,7 @@ require (
github.com/manifoldco/promptui v0.7.0
github.com/olekukonko/tablewriter v0.0.4
github.com/spf13/cobra v1.1.1
github.com/spf13/pflag v1.0.5
k8s.io/api v0.20.2
k8s.io/apiextensions-apiserver v0.20.2
k8s.io/apimachinery v0.20.2

View File

@@ -70,13 +70,19 @@ roleRef:
subjects:
- kind: ServiceAccount
name: kustomize-controller
namespace: flux-system
- kind: ServiceAccount
name: helm-controller
namespace: flux-system
- kind: ServiceAccount
name: source-controller
namespace: flux-system
- kind: ServiceAccount
name: notification-controller
namespace: flux-system
- kind: ServiceAccount
name: image-reflector-controller
namespace: flux-system
- kind: ServiceAccount
name: image-automation-controller
namespace: flux-system

View File

@@ -9,5 +9,7 @@ roleRef:
subjects:
- kind: ServiceAccount
name: kustomize-controller
namespace: flux-system
- kind: ServiceAccount
name: helm-controller
namespace: flux-system

View File

@@ -83,11 +83,11 @@ nav:
- Receiver CRD: components/notification/receiver.md
- Notification API Reference: components/notification/api.md
- Image Automation Controllers:
- Overview: components/images/controller.md
- ImageRepository CRD: components/images/imagerepositories.md
- ImagePolicy CRD: docs/components/image/imagepolicies.md
- ImageUpdateAutomation CRD: docs/components/image/imageupdateautomations.md
- Automation API Reference: docs/components/image/automation-api.md
- Overview: components/image/controller.md
- ImageRepository CRD: components/image/imagerepositories.md
- ImagePolicy CRD: components/image/imagepolicies.md
- ImageUpdateAutomation CRD: components/image/imageupdateautomations.md
- Automation API Reference: components/image/automation-api.md
- Flux CLI:
- Overview: cmd/flux.md
- Bootstrap: cmd/flux_bootstrap.md

View File

@@ -17,8 +17,10 @@ limitations under the License.
package install
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"path"
@@ -91,9 +93,23 @@ func generate(base string, options Options) error {
return fmt.Errorf("generate roles kustomization failed: %w", err)
}
if err := copyFile(filepath.Join(base, "rbac.yaml"), filepath.Join(base, "roles/rbac.yaml")); err != nil {
rbacFile := filepath.Join(base, "roles/rbac.yaml")
if err := copyFile(filepath.Join(base, "rbac.yaml"), rbacFile); err != nil {
return fmt.Errorf("generate rbac failed: %w", err)
}
// workaround for kustomize not being able to patch the SA in ClusterRoleBindings
defaultNS := MakeDefaultOptions().Namespace
if defaultNS != options.Namespace {
rbac, err := ioutil.ReadFile(rbacFile)
if err != nil {
return fmt.Errorf("reading rbac file failed: %w", err)
}
rbac = bytes.ReplaceAll(rbac, []byte(defaultNS), []byte(options.Namespace))
if err := ioutil.WriteFile(rbacFile, rbac, os.ModePerm); err != nil {
return fmt.Errorf("replacing service account namespace in rbac failed: %w", err)
}
}
return nil
}

View File

@@ -117,6 +117,7 @@ images:
var kustomizationRolesTmpl = `---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: {{.Namespace}}
resources:
- rbac.yaml
nameSuffix: -{{.Namespace}}