Skip to content

Commit

Permalink
generate gitea token (#392)
Browse files Browse the repository at this point in the history
Signed-off-by: Manabu McCloskey <[email protected]>
  • Loading branch information
nabuskey authored Oct 7, 2024
1 parent f9d4964 commit 36c22a1
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 37 deletions.
11 changes: 1 addition & 10 deletions pkg/controllers/gitrepository/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package gitrepository

import (
"context"
"crypto/tls"
"errors"
"fmt"
"net"
Expand Down Expand Up @@ -73,15 +72,7 @@ func getFallbackRepositoryURL(repo *v1alpha1.GitRepository, info repoInfo) strin
func GetGitProvider(ctx context.Context, repo *v1alpha1.GitRepository, kubeClient client.Client, scheme *runtime.Scheme, tmplConfig util.CorePackageTemplateConfig) (gitProvider, error) {
switch repo.Spec.Provider.Name {
case v1alpha1.GitProviderGitea:
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
DialContext: (&net.Dialer{
Timeout: gitTCPTimeout,
KeepAlive: 30 * time.Second, // from http.DefaultTransport
}).DialContext,
}
c := &http.Client{Transport: tr, Timeout: gitHTTPTimeout}
giteaClient, err := NewGiteaClient(repo.Spec.Provider.GitURL, gitea.SetHTTPClient(c))
giteaClient, err := NewGiteaClient(repo.Spec.Provider.GitURL, gitea.SetHTTPClient(util.GetHttpClient()))
if err != nil {
return nil, err
}
Expand Down
141 changes: 114 additions & 27 deletions pkg/controllers/localbuild/gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,33 @@ package localbuild

import (
"context"
"crypto/tls"
"embed"
"encoding/base64"
"fmt"
"net/http"
"time"

"code.gitea.io/sdk/gitea"
"github.com/cnoe-io/idpbuilder/api/v1alpha1"
"github.com/cnoe-io/idpbuilder/pkg/k8s"
"github.com/cnoe-io/idpbuilder/pkg/util"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)

const (
// hardcoded values from what we have in the yaml installation file.
giteaNamespace = "gitea"
giteaAdminSecret = "gitea-credential"
giteaNamespace = "gitea"
giteaAdminSecret = "gitea-credential"
giteaAdminTokenName = "admin"
giteaAdminTokenFieldName = "token"
// this is the URL accessible outside cluster. resolves to localhost
giteaIngressURL = "%s://gitea.cnoe.localtest.me:%s"
// this is the URL accessible within cluster for ArgoCD to fetch resources.
Expand All @@ -38,11 +43,7 @@ func RawGiteaInstallResources(templateData any, config v1alpha1.PackageCustomiza
return k8s.BuildCustomizedManifests(config.FilePath, "resources/gitea/k8s", installGiteaFS, scheme, templateData)
}

func newGiteaAdminSecret() (corev1.Secret, error) {
pass, err := util.GeneratePassword()
if err != nil {
return corev1.Secret{}, err
}
func giteaAdminSecretObject() corev1.Secret {
return corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
Expand All @@ -52,11 +53,20 @@ func newGiteaAdminSecret() (corev1.Secret, error) {
Name: giteaAdminSecret,
Namespace: giteaNamespace,
},
StringData: map[string]string{
"username": v1alpha1.GiteaAdminUserName,
"password": pass,
},
}, nil
}
}

func newGiteaAdminSecret() (corev1.Secret, error) {
pass, err := util.GeneratePassword()
if err != nil {
return corev1.Secret{}, err
}
obj := giteaAdminSecretObject()
obj.StringData = map[string]string{
"username": v1alpha1.GiteaAdminUserName,
"password": pass,
}
return obj, nil
}

func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) {
Expand All @@ -75,13 +85,25 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ
},
}

giteCreds, err := newGiteaAdminSecret()
sec := giteaAdminSecretObject()
err := r.Client.Get(ctx, types.NamespacedName{
Namespace: sec.GetNamespace(),
Name: sec.GetName(),
}, &sec)

if err != nil {
return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err)
if k8serrors.IsNotFound(err) {
giteaCreds, err := newGiteaAdminSecret()
if err != nil {
return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err)
}
gitea.unmanagedResources = []client.Object{&giteaCreds}
sec = giteaCreds
} else {
return ctrl.Result{}, fmt.Errorf("getting gitea secret: %w", err)
}
}

gitea.unmanagedResources = []client.Object{&giteCreds}

v, ok := resource.Spec.PackageConfigs.CorePackageCustomization[v1alpha1.GiteaPackageName]
if ok {
gitea.customization = v
Expand All @@ -94,16 +116,8 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ
baseUrl := giteaBaseUrl(r.Config)
// need this to ensure gitrepository controller can reach the api endpoint.
logger.V(1).Info("checking gitea api endpoint", "url", baseUrl)
c := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
Timeout: 2 * time.Second,
}
c := util.GetHttpClient()
resp, err := c.Get(baseUrl)

if err != nil {
return ctrl.Result{}, err
}
Expand All @@ -115,6 +129,11 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ
}
}

err = r.setGiteaToken(ctx, sec, baseUrl)
if err != nil {
return ctrl.Result{}, fmt.Errorf("creating gitea token: %w", err)
}

resource.Status.Gitea.ExternalURL = baseUrl
resource.Status.Gitea.InternalURL = giteaInternalBaseUrl(r.Config)
resource.Status.Gitea.AdminUserSecretName = giteaAdminSecret
Expand All @@ -123,6 +142,74 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ
return ctrl.Result{}, nil
}

func (r *LocalbuildReconciler) setGiteaToken(ctx context.Context, secret corev1.Secret, baseUrl string) error {
_, ok := secret.Data[giteaAdminTokenFieldName]
if ok {
return nil
}

u := unstructured.Unstructured{}
u.SetName(giteaAdminSecret)
u.SetNamespace(giteaNamespace)
u.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret"))

user, ok := secret.Data["username"]
if !ok {
return fmt.Errorf("username field not found in gitea secret")
}

pass, ok := secret.Data["password"]
if !ok {
return fmt.Errorf("password field not found in gitea secret")
}

t, err := getGiteaToken(ctx, baseUrl, string(user), string(pass))
if err != nil {
return fmt.Errorf("getting gitea token: %w", err)
}

token := base64.StdEncoding.EncodeToString([]byte(t))
err = unstructured.SetNestedField(u.Object, token, "data", giteaAdminTokenFieldName)
if err != nil {
return fmt.Errorf("setting gitea token field: %w", err)
}

return r.Client.Patch(ctx, &u, client.Apply, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager))
}

func getGiteaToken(ctx context.Context, baseUrl, username, password string) (string, error) {

giteaClient := gitea.NewClientWithHTTP(baseUrl, util.GetHttpClient())
giteaClient.SetBasicAuth(username, password)
giteaClient.SetContext(ctx)
tokens, resp, err := giteaClient.ListAccessTokens(gitea.ListAccessTokensOptions{})
if err != nil {
return "", fmt.Errorf("listing gitea access tokens. stauts: %s error : %w", resp.Status, err)

Check failure on line 187 in pkg/controllers/localbuild/gitea.go

View workflow job for this annotation

GitHub Actions / Check for spelling errors

stauts ==> status
}

for i := range tokens {
if tokens[i].Name == giteaAdminTokenName {
resp, err := giteaClient.DeleteAccessToken(tokens[i].ID)
if err != nil {
return "", fmt.Errorf("deleting gitea access tokens. stauts: %s error : %w", resp.Status, err)

Check failure on line 194 in pkg/controllers/localbuild/gitea.go

View workflow job for this annotation

GitHub Actions / Check for spelling errors

stauts ==> status
}
break
}
}

token, resp, err := giteaClient.CreateAccessToken(gitea.CreateAccessTokenOption{
Name: giteaAdminTokenName,
Scopes: []gitea.AccessTokenScope{
gitea.AccessTokenScopeAll,
},
})
if err != nil {
return "", fmt.Errorf("deleting gitea access tokens. stauts: %s error : %w", resp.Status, err)

Check failure on line 207 in pkg/controllers/localbuild/gitea.go

View workflow job for this annotation

GitHub Actions / Check for spelling errors

stauts ==> status
}

return token.Token, nil
}

func giteaBaseUrl(config util.CorePackageTemplateConfig) string {
return fmt.Sprintf(giteaIngressURL, config.Protocol, config.Port)
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ package util
import (
"context"
"crypto/rand"
"crypto/tls"
"fmt"
"math"
"math/big"
mathrand "math/rand"
"net"
"net/http"
"path/filepath"
"strings"
"time"

"github.com/cnoe-io/idpbuilder/api/v1alpha1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -133,3 +137,14 @@ func IsYamlFile(input string) bool {
extension := filepath.Ext(input)
return extension == ".yaml" || extension == ".yml"
}

func GetHttpClient() *http.Client {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
DialContext: (&net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 30 * time.Second, // from http.DefaultTransport
}).DialContext,
}
return &http.Client{Transport: tr, Timeout: 30 * time.Second}
}

0 comments on commit 36c22a1

Please sign in to comment.