1
0
mirror of synced 2026-05-25 18:03:33 +00:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Matheus Pimenta
04acaec616 Merge pull request #5857 from fluxcd/update-components-release/v2.8.x
Update toolkit components
2026-04-21 11:41:44 +01:00
fluxcdbot
f7dcb68bc0 Update toolkit components
- helm-controller to v1.5.4
  https://github.com/fluxcd/helm-controller/blob/v1.5.4/CHANGELOG.md
- kustomize-controller to v1.8.4
  https://github.com/fluxcd/kustomize-controller/blob/v1.8.4/CHANGELOG.md
- source-controller to v1.8.3
  https://github.com/fluxcd/source-controller/blob/v1.8.3/CHANGELOG.md
- notification-controller to v1.8.4
  https://github.com/fluxcd/notification-controller/blob/v1.8.4/CHANGELOG.md
- image-automation-controller to v1.1.2
  https://github.com/fluxcd/image-automation-controller/blob/v1.1.2/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2026-04-21 10:27:04 +00:00
Stefan Prodan
56110c02f8 Merge pull request #5837 from fluxcd/backport-5835-to-release/v2.8.x
[release/v2.8.x] Add `flux create secret receiver` command
2026-04-10 13:34:24 +03:00
Stefan Prodan
e15e2d9a34 Add --audience-claim for GCR Receivers
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
(cherry picked from commit c601a212f6)
2026-04-10 10:12:46 +00:00
Stefan Prodan
bfd59e188f Add flux create secret receiver command
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
(cherry picked from commit 02734f28ba)
2026-04-10 10:12:46 +00:00
19 changed files with 455 additions and 55 deletions

View File

@@ -30,6 +30,7 @@ import (
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils"
)
@@ -49,7 +50,7 @@ var createReceiverCmd = &cobra.Command{
}
type receiverFlags struct {
receiverType string
receiverType flags.ReceiverType
secretRef string
events []string
resources []string
@@ -58,7 +59,7 @@ type receiverFlags struct {
var receiverArgs receiverFlags
func init() {
createReceiverCmd.Flags().StringVar(&receiverArgs.receiverType, "type", "", "")
createReceiverCmd.Flags().Var(&receiverArgs.receiverType, "type", receiverArgs.receiverType.Description())
createReceiverCmd.Flags().StringVar(&receiverArgs.secretRef, "secret-ref", "", "")
createReceiverCmd.Flags().StringSliceVar(&receiverArgs.events, "event", []string{}, "also accepts comma-separated values")
createReceiverCmd.Flags().StringSliceVar(&receiverArgs.resources, "resource", []string{}, "also accepts comma-separated values")
@@ -109,7 +110,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
Labels: sourceLabels,
},
Spec: notificationv1.ReceiverSpec{
Type: receiverArgs.receiverType,
Type: receiverArgs.receiverType.String(),
Events: receiverArgs.events,
Resources: resources,
SecretRef: meta.LocalObjectReference{

View File

@@ -56,6 +56,22 @@ func upsertSecret(ctx context.Context, kubeClient client.Client, secret corev1.S
}
existing.StringData = secret.StringData
if secret.Annotations != nil {
if existing.Annotations == nil {
existing.Annotations = make(map[string]string)
}
for k, v := range secret.Annotations {
existing.Annotations[k] = v
}
}
if secret.Labels != nil {
if existing.Labels == nil {
existing.Labels = make(map[string]string)
}
for k, v := range secret.Labels {
existing.Labels[k] = v
}
}
if err := kubeClient.Update(ctx, &existing); err != nil {
return err
}

View File

@@ -0,0 +1,134 @@
/*
Copyright 2026 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"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
"github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
)
var createSecretReceiverCmd = &cobra.Command{
Use: "receiver [name]",
Short: "Create or update a Kubernetes secret for a Receiver webhook",
Long: `The create secret receiver command generates a Kubernetes secret with
the token used for webhook payload validation and an annotation with the
computed webhook URL.`,
Example: ` # Create a receiver secret for a GitHub webhook
flux create secret receiver github-receiver \
--namespace=my-namespace \
--type=github \
--hostname=flux.example.com \
--export
# Create a receiver secret for GCR with email claim
flux create secret receiver gcr-receiver \
--namespace=my-namespace \
--type=gcr \
--hostname=flux.example.com \
--email-claim=sa@project.iam.gserviceaccount.com \
--export`,
RunE: createSecretReceiverCmdRun,
}
type secretReceiverFlags struct {
receiverType flags.ReceiverType
token string
hostname string
emailClaim string
audienceClaim string
}
var secretReceiverArgs secretReceiverFlags
func init() {
createSecretReceiverCmd.Flags().Var(&secretReceiverArgs.receiverType, "type", secretReceiverArgs.receiverType.Description())
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.token, "token", "", "webhook token used for payload validation and URL computation, auto-generated if not specified")
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.hostname, "hostname", "", "hostname for the webhook URL e.g. flux.example.com")
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.emailClaim, "email-claim", "", "IAM service account email, required for gcr type")
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.audienceClaim, "audience-claim", "", "custom OIDC token audience for gcr type, defaults to the webhook URL")
createSecretCmd.AddCommand(createSecretReceiverCmd)
}
func createSecretReceiverCmdRun(cmd *cobra.Command, args []string) error {
name := args[0]
if secretReceiverArgs.receiverType == "" {
return fmt.Errorf("--type is required")
}
if secretReceiverArgs.hostname == "" {
return fmt.Errorf("--hostname is required")
}
if secretReceiverArgs.receiverType.String() == notificationv1.GCRReceiver && secretReceiverArgs.emailClaim == "" {
return fmt.Errorf("--email-claim is required for gcr receiver type")
}
labels, err := parseLabels()
if err != nil {
return err
}
opts := sourcesecret.Options{
Name: name,
Namespace: *kubeconfigArgs.Namespace,
Labels: labels,
ReceiverType: secretReceiverArgs.receiverType.String(),
Token: secretReceiverArgs.token,
Hostname: secretReceiverArgs.hostname,
EmailClaim: secretReceiverArgs.emailClaim,
AudienceClaim: secretReceiverArgs.audienceClaim,
}
secret, err := sourcesecret.GenerateReceiver(opts)
if err != nil {
return err
}
if createArgs.export {
rootCmd.Println(secret.Content)
return nil
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return err
}
var s corev1.Secret
if err := yaml.Unmarshal([]byte(secret.Content), &s); err != nil {
return err
}
if err := upsertSecret(ctx, kubeClient, s); err != nil {
return err
}
logger.Actionf("receiver secret '%s' created in '%s' namespace", name, *kubeconfigArgs.Namespace)
return nil
}

View File

@@ -0,0 +1,74 @@
/*
Copyright 2026 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 (
"testing"
)
func TestCreateReceiverSecret(t *testing.T) {
tests := []struct {
name string
args string
assert assertFunc
}{
{
name: "missing type",
args: "create secret receiver test-secret --token=t --hostname=h",
assert: assertError("--type is required"),
},
{
name: "invalid type",
args: "create secret receiver test-secret --type=invalid --token=t --hostname=h",
assert: assertError("invalid argument \"invalid\" for \"--type\" flag: receiver type 'invalid' is not supported, must be one of: generic, generic-hmac, github, gitlab, bitbucket, harbor, dockerhub, quay, gcr, nexus, acr, cdevents"),
},
{
name: "missing hostname",
args: "create secret receiver test-secret --type=github --token=t",
assert: assertError("--hostname is required"),
},
{
name: "gcr missing email-claim",
args: "create secret receiver test-secret --type=gcr --token=t --hostname=h",
assert: assertError("--email-claim is required for gcr receiver type"),
},
{
name: "github receiver secret",
args: "create secret receiver receiver-secret --type=github --token=test-token --hostname=flux.example.com --namespace=my-namespace --export",
assert: assertGoldenFile("testdata/create_secret/receiver/secret-receiver.yaml"),
},
{
name: "gcr receiver secret",
args: "create secret receiver gcr-secret --type=gcr --token=test-token --hostname=flux.example.com --email-claim=sa@project.iam.gserviceaccount.com --namespace=my-namespace --export",
assert: assertGoldenFile("testdata/create_secret/receiver/secret-receiver-gcr.yaml"),
},
{
name: "gcr receiver secret with custom audience",
args: "create secret receiver gcr-secret --type=gcr --token=test-token --hostname=flux.example.com --email-claim=sa@project.iam.gserviceaccount.com --audience-claim=https://custom.audience.example.com --namespace=my-namespace --export",
assert: assertGoldenFile("testdata/create_secret/receiver/secret-receiver-gcr-audience.yaml"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := cmdTestCase{
args: tt.args,
assert: tt.assert,
}
cmd.runTestCmd(t)
})
}
}

View File

@@ -456,6 +456,7 @@ func resetCmdArgs() {
secretGitArgs = NewSecretGitFlags()
secretGitHubAppArgs = secretGitHubAppFlags{}
secretProxyArgs = secretProxyFlags{}
secretReceiverArgs = secretReceiverFlags{}
secretHelmArgs = secretHelmFlags{}
secretTLSArgs = secretTLSFlags{}
sourceBucketArgs = sourceBucketFlags{}

View File

@@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Secret
metadata:
annotations:
notification.toolkit.fluxcd.io/webhook: https://flux.example.com/hook/6d6c55e9affb9d1e0d101ce604ae4270880ec1ff24d1bd2d928fcd64243d21a4
name: gcr-secret
namespace: my-namespace
stringData:
audience: https://custom.audience.example.com
email: sa@project.iam.gserviceaccount.com
token: test-token

View File

@@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Secret
metadata:
annotations:
notification.toolkit.fluxcd.io/webhook: https://flux.example.com/hook/6d6c55e9affb9d1e0d101ce604ae4270880ec1ff24d1bd2d928fcd64243d21a4
name: gcr-secret
namespace: my-namespace
stringData:
audience: https://flux.example.com/hook/6d6c55e9affb9d1e0d101ce604ae4270880ec1ff24d1bd2d928fcd64243d21a4
email: sa@project.iam.gserviceaccount.com
token: test-token

View File

@@ -0,0 +1,11 @@
---
apiVersion: v1
kind: Secret
metadata:
annotations:
notification.toolkit.fluxcd.io/webhook: https://flux.example.com/hook/106120121d366c2f67e93200f6c1dbe938235eb588daa5e8c0516d3a77ac1dee
name: receiver-secret
namespace: my-namespace
stringData:
token: test-token

22
go.mod
View File

@@ -12,11 +12,11 @@ require (
github.com/distribution/distribution/v3 v3.0.0
github.com/fluxcd/cli-utils v0.37.2-flux.1
github.com/fluxcd/go-git-providers v0.26.0
github.com/fluxcd/helm-controller/api v1.5.3
github.com/fluxcd/image-automation-controller/api v1.1.1
github.com/fluxcd/helm-controller/api v1.5.4
github.com/fluxcd/image-automation-controller/api v1.1.2
github.com/fluxcd/image-reflector-controller/api v1.1.1
github.com/fluxcd/kustomize-controller/api v1.8.3
github.com/fluxcd/notification-controller/api v1.8.3
github.com/fluxcd/kustomize-controller/api v1.8.4
github.com/fluxcd/notification-controller/api v1.8.4
github.com/fluxcd/pkg/apis/event v0.24.1
github.com/fluxcd/pkg/apis/meta v1.25.1
github.com/fluxcd/pkg/auth v0.38.4
@@ -31,7 +31,7 @@ require (
github.com/fluxcd/pkg/ssh v0.24.0
github.com/fluxcd/pkg/tar v0.17.0
github.com/fluxcd/pkg/version v0.12.0
github.com/fluxcd/source-controller/api v1.8.2
github.com/fluxcd/source-controller/api v1.8.3
github.com/fluxcd/source-watcher/api/v2 v2.1.1
github.com/go-git/go-git/v5 v5.16.5
github.com/go-logr/logr v1.4.3
@@ -50,9 +50,9 @@ require (
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
github.com/spf13/cobra v1.10.2
github.com/theckman/yacspin v0.13.12
golang.org/x/crypto v0.48.0
golang.org/x/term v0.40.0
golang.org/x/text v0.34.0
golang.org/x/crypto v0.50.0
golang.org/x/term v0.42.0
golang.org/x/text v0.36.0
k8s.io/api v0.35.2
k8s.io/apiextensions-apiserver v0.35.2
k8s.io/apimachinery v0.35.2
@@ -242,10 +242,10 @@ require (
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/net v0.50.0 // indirect
golang.org/x/net v0.53.0 // indirect
golang.org/x/oauth2 v0.35.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/time v0.14.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/api v0.261.0 // indirect

52
go.sum
View File

@@ -174,16 +174,16 @@ github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
github.com/fluxcd/gitkit v0.6.0/go.mod h1:svOHuKi0fO9HoawdK4HfHAJJseZDHHjk7I3ihnCIqNo=
github.com/fluxcd/go-git-providers v0.26.0 h1:0DUsXc1nS9Fe4n8tXSEUCGemWzHShd66gmotayDPekw=
github.com/fluxcd/go-git-providers v0.26.0/go.mod h1:VJDKUOhZwNAIqDF5iPtIpTr/annsDbKMkPpWiDMBdpo=
github.com/fluxcd/helm-controller/api v1.5.3 h1:ruLzuyTHjjE9A5B/U+Id2q7yHXXqSFTswdZ14xCS5So=
github.com/fluxcd/helm-controller/api v1.5.3/go.mod h1:lTgeUmtVYExMKp7mRDncsr4JwHTz3LFtLjRJZeR98lI=
github.com/fluxcd/image-automation-controller/api v1.1.1 h1:uiu7kjdVoW8/461HOemX6I7RcPornEzQliWgTg6LnWI=
github.com/fluxcd/image-automation-controller/api v1.1.1/go.mod h1:lkD/drkD6Wc+2SDjVj5KqfozEucTLFexWgby/5ft660=
github.com/fluxcd/helm-controller/api v1.5.4 h1:wbAwD+cSGBZEhT3qq1naBKkitdNbqRtWQUFNA3XTXOc=
github.com/fluxcd/helm-controller/api v1.5.4/go.mod h1:lTgeUmtVYExMKp7mRDncsr4JwHTz3LFtLjRJZeR98lI=
github.com/fluxcd/image-automation-controller/api v1.1.2 h1:Maa4qycz+iBCN/yJv9xNvuuj2IYihDAsSVwpHLhxkuk=
github.com/fluxcd/image-automation-controller/api v1.1.2/go.mod h1:lkD/drkD6Wc+2SDjVj5KqfozEucTLFexWgby/5ft660=
github.com/fluxcd/image-reflector-controller/api v1.1.1 h1:4Bj1abzVnjj8+b/293kNeFMRJc+y2wO8Z12ReZ/gA0w=
github.com/fluxcd/image-reflector-controller/api v1.1.1/go.mod h1:j4JSIocL42HQ77Veg1t60sApOy+lng8/cbXHXGSnfi0=
github.com/fluxcd/kustomize-controller/api v1.8.3 h1:Ux9AAOY0lkP6FgRg5/b/ITvRSy8lz6VBBaZ9bXmTLmI=
github.com/fluxcd/kustomize-controller/api v1.8.3/go.mod h1:c/mUPIffDDLg1EicXCJtX4N/rc+z5Zh0e/CXjhd7Dyc=
github.com/fluxcd/notification-controller/api v1.8.3 h1:edYpC/t4pNw/KQur189SRC1XtFNU597ooDTCrW90Xmw=
github.com/fluxcd/notification-controller/api v1.8.3/go.mod h1:ozgJGQPy0dG5eOsLZlwAr6n0q/y6+TWd1fGOtavlXJA=
github.com/fluxcd/kustomize-controller/api v1.8.4 h1:13+9CgxGj67Bn7wzFILw8S4r4urEgiLTODwjA4XU0mU=
github.com/fluxcd/kustomize-controller/api v1.8.4/go.mod h1:c/mUPIffDDLg1EicXCJtX4N/rc+z5Zh0e/CXjhd7Dyc=
github.com/fluxcd/notification-controller/api v1.8.4 h1:KhHHVhQNtQsY+cVm/Y/8vhhFfrEOxM2AL/8JF8LAjMg=
github.com/fluxcd/notification-controller/api v1.8.4/go.mod h1:ozgJGQPy0dG5eOsLZlwAr6n0q/y6+TWd1fGOtavlXJA=
github.com/fluxcd/pkg/apis/acl v0.9.0 h1:wBpgsKT+jcyZEcM//OmZr9RiF8klL3ebrDp2u2ThsnA=
github.com/fluxcd/pkg/apis/acl v0.9.0/go.mod h1:TttNS+gocsGLwnvmgVi3/Yscwqrjc17+vhgYfqkfrV4=
github.com/fluxcd/pkg/apis/event v0.24.1 h1:TClVdn02aiq3sAl9BuzLjjTIxm3JJ83fJ9nchtBa4qg=
@@ -220,8 +220,8 @@ github.com/fluxcd/pkg/tar v0.17.0 h1:uNxbFXy8ly8C7fJ8D7w3rjTNJFrb4Hp1aY/30XkfvxY
github.com/fluxcd/pkg/tar v0.17.0/go.mod h1:b1xyIRYDD0ket4SV5u0UXYv+ZdN/O/HmIO5jZQdHQls=
github.com/fluxcd/pkg/version v0.12.0 h1:MGbdbNf2D5wazMqAkNPn+Lh5j+oY0gxQJFTGyet5Hfc=
github.com/fluxcd/pkg/version v0.12.0/go.mod h1:YHdg/78kzf+kCqS+SqSOiUxum5AjxlixiqwpX6AUZB8=
github.com/fluxcd/source-controller/api v1.8.2 h1:i0/6BeNCn+zRfX+gKh4PsFF2NBzBhwXt0wPImVlZObg=
github.com/fluxcd/source-controller/api v1.8.2/go.mod h1:HgZ6NSH1cyOE2jRoNwln1xEwr9ETvrLeiy1o4O04vQM=
github.com/fluxcd/source-controller/api v1.8.3 h1:WNEETjmp/YTZx5IMg9ewz2Wn8YzOVETeJJ0LIPivm40=
github.com/fluxcd/source-controller/api v1.8.3/go.mod h1:sio4t49RDx+S1etHRFAEEw8qfVuw0KKlOg8bRVlEYPM=
github.com/fluxcd/source-watcher/api/v2 v2.1.1 h1:1LfT50ty+78MKKbschAZl28QbVqIyjaNq17KmW5wPJI=
github.com/fluxcd/source-watcher/api/v2 v2.1.1/go.mod h1:6M1BzBGQRoIuSenSQlfJHwMVVobFPiNPxXqfN0IILc4=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
@@ -619,15 +619,15 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -643,8 +643,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -656,8 +656,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -683,8 +683,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -694,8 +694,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -706,8 +706,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -716,8 +716,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=

View File

@@ -0,0 +1,68 @@
/*
Copyright 2026 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 flags
import (
"fmt"
"strings"
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
"github.com/fluxcd/flux2/v2/internal/utils"
)
var supportedReceiverTypes = []string{
notificationv1.GenericReceiver,
notificationv1.GenericHMACReceiver,
notificationv1.GitHubReceiver,
notificationv1.GitLabReceiver,
notificationv1.BitbucketReceiver,
notificationv1.HarborReceiver,
notificationv1.DockerHubReceiver,
notificationv1.QuayReceiver,
notificationv1.GCRReceiver,
notificationv1.NexusReceiver,
notificationv1.ACRReceiver,
notificationv1.CDEventsReceiver,
}
type ReceiverType string
func (r *ReceiverType) String() string {
return string(*r)
}
func (r *ReceiverType) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no receiver type given, please specify %s",
r.Description())
}
if !utils.ContainsItemString(supportedReceiverTypes, str) {
return fmt.Errorf("receiver type '%s' is not supported, must be one of: %s",
str, strings.Join(supportedReceiverTypes, ", "))
}
*r = ReceiverType(str)
return nil
}
func (r *ReceiverType) Type() string {
return strings.Join(supportedReceiverTypes, "|")
}
func (r *ReceiverType) Description() string {
return "the receiver type"
}

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.3/helm-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.3/helm-controller.deployment.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.4/helm-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.4/helm-controller.deployment.yaml
- account.yaml
transformers:
- labels.yaml

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.1/image-automation-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.1/image-automation-controller.deployment.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.2/image-automation-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.2/image-automation-controller.deployment.yaml
- account.yaml
transformers:
- labels.yaml

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.3/kustomize-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.3/kustomize-controller.deployment.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.4/kustomize-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.4/kustomize-controller.deployment.yaml
- account.yaml
transformers:
- labels.yaml

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.3/notification-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.3/notification-controller.deployment.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.4/notification-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.4/notification-controller.deployment.yaml
- account.yaml
transformers:
- labels.yaml

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/source-controller/releases/download/v1.8.2/source-controller.crds.yaml
- https://github.com/fluxcd/source-controller/releases/download/v1.8.2/source-controller.deployment.yaml
- https://github.com/fluxcd/source-controller/releases/download/v1.8.3/source-controller.crds.yaml
- https://github.com/fluxcd/source-controller/releases/download/v1.8.3/source-controller.deployment.yaml
- account.yaml
transformers:
- labels.yaml

View File

@@ -1,10 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/source-controller/releases/download/v1.8.2/source-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.3/kustomize-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.3/helm-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.3/notification-controller.crds.yaml
- https://github.com/fluxcd/source-controller/releases/download/v1.8.3/source-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.4/kustomize-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.4/helm-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.4/notification-controller.crds.yaml
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.1.1/image-reflector-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.1/image-automation-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.2/image-automation-controller.crds.yaml
- https://github.com/fluxcd/source-watcher/releases/download/v2.1.1/source-watcher.crds.yaml

View File

@@ -42,6 +42,12 @@ const (
KnownHostsSecretKey = "known_hosts"
BearerTokenKey = "bearerToken"
TrustPolicyKey = "trustpolicy.json"
TokenSecretKey = "token"
EmailSecretKey = "email"
AudienceSecretKey = "audience"
// WebhookURLAnnotation is the annotation key for the computed webhook URL.
WebhookURLAnnotation = "notification.toolkit.fluxcd.io/webhook"
// Deprecated: Replaced by CACrtSecretKey, but kept for backwards
// compatibility with deprecated TLS flags.
@@ -82,6 +88,13 @@ type Options struct {
GitHubAppInstallationID string
GitHubAppPrivateKey string
GitHubAppBaseURL string
// Receiver options
ReceiverType string
Token string
Hostname string
EmailClaim string
AudienceClaim string
}
type VerificationCrt struct {

View File

@@ -18,7 +18,10 @@ package sourcesecret
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"net"
@@ -260,6 +263,59 @@ func GenerateGitHubApp(options Options) (*manifestgen.Manifest, error) {
return secretToManifest(secret, options)
}
func GenerateReceiver(options Options) (*manifestgen.Manifest, error) {
token := options.Token
if token == "" {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
return nil, fmt.Errorf("failed to generate random token: %w", err)
}
token = hex.EncodeToString(b)
}
if options.Hostname == "" {
return nil, fmt.Errorf("hostname is required")
}
// Compute the webhook path using the same algorithm as notification-controller.
// See: github.com/fluxcd/notification-controller/api/v1.Receiver.GetWebhookPath
digest := sha256.Sum256([]byte(token + options.Name + options.Namespace))
webhookPath := fmt.Sprintf("/hook/%x", digest)
webhookURL := fmt.Sprintf("https://%s%s", options.Hostname, webhookPath)
secret := &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: options.Name,
Namespace: options.Namespace,
Labels: options.Labels,
Annotations: map[string]string{
WebhookURLAnnotation: webhookURL,
},
},
StringData: map[string]string{
TokenSecretKey: token,
},
}
if options.ReceiverType == "gcr" {
if options.EmailClaim == "" {
return nil, fmt.Errorf("email-claim is required for gcr receiver type")
}
secret.StringData[EmailSecretKey] = options.EmailClaim
if options.AudienceClaim != "" {
secret.StringData[AudienceSecretKey] = options.AudienceClaim
} else {
secret.StringData[AudienceSecretKey] = webhookURL
}
}
return secretToManifest(secret, options)
}
func LoadKeyPairFromPath(path, password string) (*ssh.KeyPair, error) {
if path == "" {
return nil, nil