diff --git a/cmd/flux/create_secret_github_app.go b/cmd/flux/create_secret_github_app.go new file mode 100644 index 00000000..71f06038 --- /dev/null +++ b/cmd/flux/create_secret_github_app.go @@ -0,0 +1,128 @@ +/* +Copyright 2024 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" + "os" + + "github.com/fluxcd/flux2/v2/internal/utils" + "github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret" + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" +) + +var createSecretGitHubAppCmd = &cobra.Command{ + Use: "githubapp [name]", + Short: "Create or update a github app secret", + Long: withPreviewNote(`The create secret githubapp command generates a Kubernetes secret that can be used for GitRepository authentication with github app`), + Example: ` # Create a githubapp authentication secret on disk and encrypt it with Mozilla SOPS + flux create secret githubapp podinfo-auth \ + --app-id="1" \ + --app-installation-id="2" \ + --app-private-key=./private-key-file.pem \ + --export > githubapp-auth.yaml + + sops --encrypt --encrypted-regex '^(data|stringData)$' \ + --in-place githubapp-auth.yaml + `, + RunE: createSecretGitHubAppCmdRun, +} + +type secretGitHubAppFlags struct { + appID string + appInstallationID string + privateKeyFile string + baseURL string +} + +var secretGitHubAppArgs = secretGitHubAppFlags{} + +func init() { + createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.appID, "app-id", "", "github app ID") + createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.appInstallationID, "app-installation-id", "", "github app installation ID") + createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.privateKeyFile, "app-private-key", "", "github app private key file path") + createSecretGitHubAppCmd.Flags().StringVar(&secretGitHubAppArgs.baseURL, "app-base-url", "", "github app base URL") + + createSecretCmd.AddCommand(createSecretGitHubAppCmd) +} + +func createSecretGitHubAppCmdRun(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("name is required") + } + + secretName := args[0] + + if secretGitHubAppArgs.appID == "" { + return fmt.Errorf("--app-id is required") + } + + if secretGitHubAppArgs.appInstallationID == "" { + return fmt.Errorf("--app-installation-id is required") + } + + if secretGitHubAppArgs.privateKeyFile == "" { + return fmt.Errorf("--app-private-key is required") + } + + privateKey, err := os.ReadFile(secretGitHubAppArgs.privateKeyFile) + if err != nil { + return fmt.Errorf("unable to read private key file: %w", err) + } + + opts := sourcesecret.Options{ + Name: secretName, + Namespace: *kubeconfigArgs.Namespace, + GitHubAppID: secretGitHubAppArgs.appID, + GitHubAppInstallationID: secretGitHubAppArgs.appInstallationID, + GitHubAppPrivateKey: string(privateKey), + } + + if secretGitHubAppArgs.baseURL != "" { + opts.GitHubAppBaseURL = secretGitHubAppArgs.baseURL + } + + secret, err := sourcesecret.Generate(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("githubapp secret '%s' created in '%s' namespace", secretName, *kubeconfigArgs.Namespace) + return nil +} diff --git a/cmd/flux/create_secret_githubapp_test.go b/cmd/flux/create_secret_githubapp_test.go new file mode 100644 index 00000000..7ea0275f --- /dev/null +++ b/cmd/flux/create_secret_githubapp_test.go @@ -0,0 +1,74 @@ +/* +Copyright 2022 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 TestCreateSecretGitHubApp(t *testing.T) { + tests := []struct { + name string + args string + assert assertFunc + }{ + { + name: "create githubapp secret with missing name", + args: "create secret githubapp", + assert: assertError("name is required"), + }, + { + name: "create githubapp secret with missing app-id", + args: "create secret githubapp appinfo", + assert: assertError("--app-id is required"), + }, + { + name: "create githubapp secret with missing appInstallationID", + args: "create secret githubapp appinfo --app-id 1", + assert: assertError("--app-installation-id is required"), + }, + { + name: "create githubapp secret with missing private key file", + args: "create secret githubapp appinfo --app-id 1 --app-installation-id 2", + assert: assertError("--app-private-key is required"), + }, + { + name: "create githubapp secret with private key file that does not exist", + args: "create secret githubapp appinfo --app-id 1 --app-installation-id 2 --app-private-key pk.pem", + assert: assertError("unable to read private key file: open pk.pem: no such file or directory"), + }, + { + name: "create githubapp secret with app info", + args: "create secret githubapp appinfo --namespace my-namespace --app-id 1 --app-installation-id 2 --app-private-key ./testdata/create_secret/githubapp/test-private-key.pem --export", + assert: assertGoldenFile("testdata/create_secret/githubapp/secret.yaml"), + }, + { + name: "create githubapp secret with appinfo and base url", + args: "create secret githubapp appinfo --namespace my-namespace --app-id 1 --app-installation-id 2 --app-private-key ./testdata/create_secret/githubapp/test-private-key.pem --app-base-url www.example.com/api/v3 --export", + assert: assertGoldenFile("testdata/create_secret/githubapp/secret-with-baseurl.yaml"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := cmdTestCase{ + args: tt.args, + assert: tt.assert, + } + cmd.runTestCmd(t) + }) + } +} diff --git a/cmd/flux/create_source_git.go b/cmd/flux/create_source_git.go index b8a4787a..176daf7f 100644 --- a/cmd/flux/create_source_git.go +++ b/cmd/flux/create_source_git.go @@ -145,7 +145,7 @@ func init() { createSourceGitCmd.Flags().Var(&sourceGitArgs.keyAlgorithm, "ssh-key-algorithm", sourceGitArgs.keyAlgorithm.Description()) createSourceGitCmd.Flags().Var(&sourceGitArgs.keyRSABits, "ssh-rsa-bits", sourceGitArgs.keyRSABits.Description()) createSourceGitCmd.Flags().Var(&sourceGitArgs.keyECDSACurve, "ssh-ecdsa-curve", sourceGitArgs.keyECDSACurve.Description()) - createSourceGitCmd.Flags().StringVar(&sourceGitArgs.secretRef, "secret-ref", "", "the name of an existing secret containing SSH or basic credentials") + createSourceGitCmd.Flags().StringVar(&sourceGitArgs.secretRef, "secret-ref", "", "the name of an existing secret containing SSH or basic credentials or github app authentication") createSourceGitCmd.Flags().StringVar(&sourceGitArgs.proxySecretRef, "proxy-secret-ref", "", "the name of an existing secret containing the proxy address and credentials") createSourceGitCmd.Flags().Var(&sourceGitArgs.provider, "provider", sourceGitArgs.provider.Description()) createSourceGitCmd.Flags().StringVar(&sourceGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates") diff --git a/cmd/flux/create_source_git_test.go b/cmd/flux/create_source_git_test.go index d2ece636..a04ee5c9 100644 --- a/cmd/flux/create_source_git_test.go +++ b/cmd/flux/create_source_git_test.go @@ -144,10 +144,15 @@ func TestCreateSourceGitExport(t *testing.T) { args: "create source git podinfo --namespace=flux-system --url=https://dev.azure.com/foo/bar/_git/podinfo --provider azure --branch=test --interval=1m0s --export", assert: assertGoldenFile("testdata/create_source_git/source-git-provider-azure.yaml"), }, + { + name: "source with github provider", + args: "create source git podinfo --namespace=flux-system --url=https://github.com/stefanprodan/podinfo --provider github --branch=test --interval=1m0s --secret-ref appinfo --export", + assert: assertGoldenFile("testdata/create_source_git/source-git-provider-github.yaml"), + }, { name: "source with invalid provider", args: "create source git podinfo --namespace=flux-system --url=https://dev.azure.com/foo/bar/_git/podinfo --provider dummy --branch=test --interval=1m0s --export", - assert: assertError("invalid argument \"dummy\" for \"--provider\" flag: source Git provider 'dummy' is not supported, must be one of: generic|azure"), + assert: assertError("invalid argument \"dummy\" for \"--provider\" flag: source Git provider 'dummy' is not supported, must be one of: generic|azure|github"), }, { name: "source with empty provider", diff --git a/cmd/flux/testdata/create_secret/githubapp/secret-with-baseurl.yaml b/cmd/flux/testdata/create_secret/githubapp/secret-with-baseurl.yaml new file mode 100644 index 00000000..365a7bfe --- /dev/null +++ b/cmd/flux/testdata/create_secret/githubapp/secret-with-baseurl.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: appinfo + namespace: my-namespace +stringData: + githubAppBaseURL: www.example.com/api/v3 + githubAppID: "1" + githubAppInstallationID: "2" + githubAppPrivateKey: |- + -----BEGIN RSA PRIVATE KEY----- + YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap + PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm + zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm + LsXqL2iZvVvCH0FiDwBIfxAMhl6fnPzuQsZBiRLPdD67jubPseN1P5JBRw3WTton + Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T + MROFeZmxBHYon1Y4Rw+jCSXovNyHbMBpMI67nwIDAQABAoIBAC4UrkusU8r7ilFu + w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB + FkhEBrwXKnh499iiO/SUo+7kaq0WLQ7mQ2Q9wpMmkkjnr0tgydAno/uNNITSaqmk + YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap + Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T + zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm + ihlXNkECgYEA3abZJZuVarHPlAqRYkprs0O+DrP6sPlmVQp+nq8y3Qg00U+N7AuP + Y1riLo3gWq7LajkGTygWLmru2mhWsETxt+R4BtnREUq8kDEoCfEwPlHfqfphvBZL + j5eL60QTKAqSOVqMgIzqJyxa5FGgPGqWpLDLopyVeoyNdZwcuCQzFgkCgYEA25dm + PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm + MkvaCGIAH+lfJrtTSujFaOIGFy+0ZwP+LNqHUKih14y8Qv9dEP0kaXkAD3fO3Y97 + Nj+Q2c06JpojgBKBMwVvT7M53w9KEoNKpoKBbmcCgYBelHyiRJJsdbVKyXuiAnmU + g/qMkZYOgE1/SjwfgEjm8kJ/cj/wEjq8PaK4FMhAScf46p5blpJoei6zucQL8U9n + lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s + dNhf6gsKwQD3x4aluKSn6QKBgD8HbvBAKV6P4vIiFzS0QvWtpeKam2EDHI+h+WsP + nD77QoG/EPvpjJS9/KWgZRPz6U+0M5V0y73MZVzkbbVT/uwfgF2G91lXAr4Kfuh5 + w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB + qCEDAoGACl8ClvMJR2uNWdaWnCz9tyPdHYgEusJ0OIP+WUY2ToYQWSlA0zNpc21Y + lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s + bUytJtOhHbLRNxwgalhjBUNWICrDktqJmumNOEOOPBqVz7RGwUg= + -----END RSA PRIVATE KEY----- + diff --git a/cmd/flux/testdata/create_secret/githubapp/secret.yaml b/cmd/flux/testdata/create_secret/githubapp/secret.yaml new file mode 100644 index 00000000..5948d00c --- /dev/null +++ b/cmd/flux/testdata/create_secret/githubapp/secret.yaml @@ -0,0 +1,38 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: appinfo + namespace: my-namespace +stringData: + githubAppID: "1" + githubAppInstallationID: "2" + githubAppPrivateKey: |- + -----BEGIN RSA PRIVATE KEY----- + YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap + PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm + zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm + LsXqL2iZvVvCH0FiDwBIfxAMhl6fnPzuQsZBiRLPdD67jubPseN1P5JBRw3WTton + Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T + MROFeZmxBHYon1Y4Rw+jCSXovNyHbMBpMI67nwIDAQABAoIBAC4UrkusU8r7ilFu + w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB + FkhEBrwXKnh499iiO/SUo+7kaq0WLQ7mQ2Q9wpMmkkjnr0tgydAno/uNNITSaqmk + YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap + Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T + zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm + ihlXNkECgYEA3abZJZuVarHPlAqRYkprs0O+DrP6sPlmVQp+nq8y3Qg00U+N7AuP + Y1riLo3gWq7LajkGTygWLmru2mhWsETxt+R4BtnREUq8kDEoCfEwPlHfqfphvBZL + j5eL60QTKAqSOVqMgIzqJyxa5FGgPGqWpLDLopyVeoyNdZwcuCQzFgkCgYEA25dm + PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm + MkvaCGIAH+lfJrtTSujFaOIGFy+0ZwP+LNqHUKih14y8Qv9dEP0kaXkAD3fO3Y97 + Nj+Q2c06JpojgBKBMwVvT7M53w9KEoNKpoKBbmcCgYBelHyiRJJsdbVKyXuiAnmU + g/qMkZYOgE1/SjwfgEjm8kJ/cj/wEjq8PaK4FMhAScf46p5blpJoei6zucQL8U9n + lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s + dNhf6gsKwQD3x4aluKSn6QKBgD8HbvBAKV6P4vIiFzS0QvWtpeKam2EDHI+h+WsP + nD77QoG/EPvpjJS9/KWgZRPz6U+0M5V0y73MZVzkbbVT/uwfgF2G91lXAr4Kfuh5 + w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB + qCEDAoGACl8ClvMJR2uNWdaWnCz9tyPdHYgEusJ0OIP+WUY2ToYQWSlA0zNpc21Y + lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s + bUytJtOhHbLRNxwgalhjBUNWICrDktqJmumNOEOOPBqVz7RGwUg= + -----END RSA PRIVATE KEY----- + diff --git a/cmd/flux/testdata/create_secret/githubapp/test-private-key.pem b/cmd/flux/testdata/create_secret/githubapp/test-private-key.pem new file mode 100644 index 00000000..afe4b7c4 --- /dev/null +++ b/cmd/flux/testdata/create_secret/githubapp/test-private-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap +PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm +zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm +LsXqL2iZvVvCH0FiDwBIfxAMhl6fnPzuQsZBiRLPdD67jubPseN1P5JBRw3WTton +Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T +MROFeZmxBHYon1Y4Rw+jCSXovNyHbMBpMI67nwIDAQABAoIBAC4UrkusU8r7ilFu +w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB +FkhEBrwXKnh499iiO/SUo+7kaq0WLQ7mQ2Q9wpMmkkjnr0tgydAno/uNNITSaqmk +YcE2CgWILk+uiVNseHnOU2frG7k2RJZtdDo8GNI6pQWFlwU/NsQoJBrtEDyYVkap +Fa2RLLByuyge7bWh2o1hjEx2w2ZpIhosQRyDs1sPXP5TI92RzOcx1CZaTZ6V5E+T +zSde2KD/ilB1YUhaAv0qaBHLTGBvVgxut1eIyvqVC+ArWoqJ7rQTst+Arp3UAiIm +ihlXNkECgYEA3abZJZuVarHPlAqRYkprs0O+DrP6sPlmVQp+nq8y3Qg00U+N7AuP +Y1riLo3gWq7LajkGTygWLmru2mhWsETxt+R4BtnREUq8kDEoCfEwPlHfqfphvBZL +j5eL60QTKAqSOVqMgIzqJyxa5FGgPGqWpLDLopyVeoyNdZwcuCQzFgkCgYEA25dm +PLv7VoJ2pr6l5IEwH++naL2McuCcwhW/CeaVb/IuSCFFMwb40zRrlqp6IB5VkMhm +MkvaCGIAH+lfJrtTSujFaOIGFy+0ZwP+LNqHUKih14y8Qv9dEP0kaXkAD3fO3Y97 +Nj+Q2c06JpojgBKBMwVvT7M53w9KEoNKpoKBbmcCgYBelHyiRJJsdbVKyXuiAnmU +g/qMkZYOgE1/SjwfgEjm8kJ/cj/wEjq8PaK4FMhAScf46p5blpJoei6zucQL8U9n +lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s +dNhf6gsKwQD3x4aluKSn6QKBgD8HbvBAKV6P4vIiFzS0QvWtpeKam2EDHI+h+WsP +nD77QoG/EPvpjJS9/KWgZRPz6U+0M5V0y73MZVzkbbVT/uwfgF2G91lXAr4Kfuh5 +w1LWDm09+8WSIk9KgYMoBceAqH+b9DU7hrMFrKkO/cr0Mijr1somv6B3MG83WUcB +qCEDAoGACl8ClvMJR2uNWdaWnCz9tyPdHYgEusJ0OIP+WUY2ToYQWSlA0zNpc21Y +lbD102oXw9lUefVI0McyQIN9J58ewDC79AG7gU/fTSt6F75OeFLOJmoedQo33Y+s +bUytJtOhHbLRNxwgalhjBUNWICrDktqJmumNOEOOPBqVz7RGwUg= +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/cmd/flux/testdata/create_source_git/source-git-provider-github.yaml b/cmd/flux/testdata/create_source_git/source-git-provider-github.yaml new file mode 100644 index 00000000..5bdd1deb --- /dev/null +++ b/cmd/flux/testdata/create_source_git/source-git-provider-github.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: podinfo + namespace: flux-system +spec: + interval: 1m0s + provider: github + ref: + branch: test + secretRef: + name: appinfo + url: https://github.com/stefanprodan/podinfo diff --git a/go.mod b/go.mod index 4243e625..702eefc9 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/fluxcd/notification-controller/api v1.5.0 github.com/fluxcd/pkg/apis/event v0.16.0 github.com/fluxcd/pkg/apis/meta v1.10.0 + github.com/fluxcd/pkg/auth v0.3.0 github.com/fluxcd/pkg/chartutil v1.2.0 github.com/fluxcd/pkg/envsubst v1.3.0 github.com/fluxcd/pkg/git v0.24.0 @@ -119,7 +120,6 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fluxcd/pkg/apis/acl v0.6.0 // indirect github.com/fluxcd/pkg/apis/kustomize v1.9.0 // indirect - github.com/fluxcd/pkg/auth v0.3.0 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect diff --git a/internal/flags/source_git_provider.go b/internal/flags/source_git_provider.go index 63cec33e..fb2e6c5b 100644 --- a/internal/flags/source_git_provider.go +++ b/internal/flags/source_git_provider.go @@ -27,6 +27,7 @@ import ( var supportedSourceGitProviders = []string{ sourcev1.GitProviderGeneric, sourcev1.GitProviderAzure, + sourcev1.GitProviderGitHub, } type SourceGitProvider string diff --git a/pkg/manifestgen/sourcesecret/options.go b/pkg/manifestgen/sourcesecret/options.go index 6bf4e3cc..79d6941a 100644 --- a/pkg/manifestgen/sourcesecret/options.go +++ b/pkg/manifestgen/sourcesecret/options.go @@ -75,6 +75,12 @@ type Options struct { VerificationCrts []VerificationCrt TrustPolicy []byte Address string + + // GitHub App options + GitHubAppID string + GitHubAppInstallationID string + GitHubAppPrivateKey string + GitHubAppBaseURL string } type VerificationCrt struct { diff --git a/pkg/manifestgen/sourcesecret/sourcesecret.go b/pkg/manifestgen/sourcesecret/sourcesecret.go index 8b680c3d..cc884ca8 100644 --- a/pkg/manifestgen/sourcesecret/sourcesecret.go +++ b/pkg/manifestgen/sourcesecret/sourcesecret.go @@ -31,6 +31,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" + "github.com/fluxcd/pkg/auth/github" "github.com/fluxcd/pkg/ssh" "github.com/fluxcd/flux2/v2/pkg/manifestgen" @@ -190,6 +191,22 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, dockerCfg []byte, options Option secret.StringData[TrustPolicyKey] = string(options.TrustPolicy) } + if options.GitHubAppID != "" { + secret.StringData[github.AppIDKey] = options.GitHubAppID + } + + if options.GitHubAppInstallationID != "" { + secret.StringData[github.AppInstallationIDKey] = options.GitHubAppInstallationID + } + + if options.GitHubAppPrivateKey != "" { + secret.StringData[github.AppPrivateKey] = options.GitHubAppPrivateKey + } + + if options.GitHubAppBaseURL != "" { + secret.StringData[github.AppBaseUrlKey] = options.GitHubAppBaseURL + } + return }