Skip to content

Commit 36c22a1

Browse files
authored
generate gitea token (#392)
Signed-off-by: Manabu McCloskey <[email protected]>
1 parent f9d4964 commit 36c22a1

File tree

3 files changed

+130
-37
lines changed

3 files changed

+130
-37
lines changed

pkg/controllers/gitrepository/controller.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package gitrepository
22

33
import (
44
"context"
5-
"crypto/tls"
65
"errors"
76
"fmt"
87
"net"
@@ -73,15 +72,7 @@ func getFallbackRepositoryURL(repo *v1alpha1.GitRepository, info repoInfo) strin
7372
func GetGitProvider(ctx context.Context, repo *v1alpha1.GitRepository, kubeClient client.Client, scheme *runtime.Scheme, tmplConfig util.CorePackageTemplateConfig) (gitProvider, error) {
7473
switch repo.Spec.Provider.Name {
7574
case v1alpha1.GitProviderGitea:
76-
tr := &http.Transport{
77-
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
78-
DialContext: (&net.Dialer{
79-
Timeout: gitTCPTimeout,
80-
KeepAlive: 30 * time.Second, // from http.DefaultTransport
81-
}).DialContext,
82-
}
83-
c := &http.Client{Transport: tr, Timeout: gitHTTPTimeout}
84-
giteaClient, err := NewGiteaClient(repo.Spec.Provider.GitURL, gitea.SetHTTPClient(c))
75+
giteaClient, err := NewGiteaClient(repo.Spec.Provider.GitURL, gitea.SetHTTPClient(util.GetHttpClient()))
8576
if err != nil {
8677
return nil, err
8778
}

pkg/controllers/localbuild/gitea.go

Lines changed: 114 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,33 @@ package localbuild
22

33
import (
44
"context"
5-
"crypto/tls"
65
"embed"
6+
"encoding/base64"
77
"fmt"
88
"net/http"
9-
"time"
109

10+
"code.gitea.io/sdk/gitea"
1111
"github.com/cnoe-io/idpbuilder/api/v1alpha1"
1212
"github.com/cnoe-io/idpbuilder/pkg/k8s"
1313
"github.com/cnoe-io/idpbuilder/pkg/util"
1414
corev1 "k8s.io/api/core/v1"
15+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
1516
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1618
"k8s.io/apimachinery/pkg/runtime"
1719
"k8s.io/apimachinery/pkg/runtime/schema"
20+
"k8s.io/apimachinery/pkg/types"
1821
ctrl "sigs.k8s.io/controller-runtime"
1922
"sigs.k8s.io/controller-runtime/pkg/client"
2023
"sigs.k8s.io/controller-runtime/pkg/log"
2124
)
2225

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

41-
func newGiteaAdminSecret() (corev1.Secret, error) {
42-
pass, err := util.GeneratePassword()
43-
if err != nil {
44-
return corev1.Secret{}, err
45-
}
46+
func giteaAdminSecretObject() corev1.Secret {
4647
return corev1.Secret{
4748
TypeMeta: metav1.TypeMeta{
4849
Kind: "Secret",
@@ -52,11 +53,20 @@ func newGiteaAdminSecret() (corev1.Secret, error) {
5253
Name: giteaAdminSecret,
5354
Namespace: giteaNamespace,
5455
},
55-
StringData: map[string]string{
56-
"username": v1alpha1.GiteaAdminUserName,
57-
"password": pass,
58-
},
59-
}, nil
56+
}
57+
}
58+
59+
func newGiteaAdminSecret() (corev1.Secret, error) {
60+
pass, err := util.GeneratePassword()
61+
if err != nil {
62+
return corev1.Secret{}, err
63+
}
64+
obj := giteaAdminSecretObject()
65+
obj.StringData = map[string]string{
66+
"username": v1alpha1.GiteaAdminUserName,
67+
"password": pass,
68+
}
69+
return obj, nil
6070
}
6171

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

78-
giteCreds, err := newGiteaAdminSecret()
88+
sec := giteaAdminSecretObject()
89+
err := r.Client.Get(ctx, types.NamespacedName{
90+
Namespace: sec.GetNamespace(),
91+
Name: sec.GetName(),
92+
}, &sec)
93+
7994
if err != nil {
80-
return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err)
95+
if k8serrors.IsNotFound(err) {
96+
giteaCreds, err := newGiteaAdminSecret()
97+
if err != nil {
98+
return ctrl.Result{}, fmt.Errorf("generating gitea admin secret: %w", err)
99+
}
100+
gitea.unmanagedResources = []client.Object{&giteaCreds}
101+
sec = giteaCreds
102+
} else {
103+
return ctrl.Result{}, fmt.Errorf("getting gitea secret: %w", err)
104+
}
81105
}
82106

83-
gitea.unmanagedResources = []client.Object{&giteCreds}
84-
85107
v, ok := resource.Spec.PackageConfigs.CorePackageCustomization[v1alpha1.GiteaPackageName]
86108
if ok {
87109
gitea.customization = v
@@ -94,16 +116,8 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ
94116
baseUrl := giteaBaseUrl(r.Config)
95117
// need this to ensure gitrepository controller can reach the api endpoint.
96118
logger.V(1).Info("checking gitea api endpoint", "url", baseUrl)
97-
c := &http.Client{
98-
Transport: &http.Transport{
99-
TLSClientConfig: &tls.Config{
100-
InsecureSkipVerify: true,
101-
},
102-
},
103-
Timeout: 2 * time.Second,
104-
}
119+
c := util.GetHttpClient()
105120
resp, err := c.Get(baseUrl)
106-
107121
if err != nil {
108122
return ctrl.Result{}, err
109123
}
@@ -115,6 +129,11 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ
115129
}
116130
}
117131

132+
err = r.setGiteaToken(ctx, sec, baseUrl)
133+
if err != nil {
134+
return ctrl.Result{}, fmt.Errorf("creating gitea token: %w", err)
135+
}
136+
118137
resource.Status.Gitea.ExternalURL = baseUrl
119138
resource.Status.Gitea.InternalURL = giteaInternalBaseUrl(r.Config)
120139
resource.Status.Gitea.AdminUserSecretName = giteaAdminSecret
@@ -123,6 +142,74 @@ func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Requ
123142
return ctrl.Result{}, nil
124143
}
125144

145+
func (r *LocalbuildReconciler) setGiteaToken(ctx context.Context, secret corev1.Secret, baseUrl string) error {
146+
_, ok := secret.Data[giteaAdminTokenFieldName]
147+
if ok {
148+
return nil
149+
}
150+
151+
u := unstructured.Unstructured{}
152+
u.SetName(giteaAdminSecret)
153+
u.SetNamespace(giteaNamespace)
154+
u.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret"))
155+
156+
user, ok := secret.Data["username"]
157+
if !ok {
158+
return fmt.Errorf("username field not found in gitea secret")
159+
}
160+
161+
pass, ok := secret.Data["password"]
162+
if !ok {
163+
return fmt.Errorf("password field not found in gitea secret")
164+
}
165+
166+
t, err := getGiteaToken(ctx, baseUrl, string(user), string(pass))
167+
if err != nil {
168+
return fmt.Errorf("getting gitea token: %w", err)
169+
}
170+
171+
token := base64.StdEncoding.EncodeToString([]byte(t))
172+
err = unstructured.SetNestedField(u.Object, token, "data", giteaAdminTokenFieldName)
173+
if err != nil {
174+
return fmt.Errorf("setting gitea token field: %w", err)
175+
}
176+
177+
return r.Client.Patch(ctx, &u, client.Apply, client.ForceOwnership, client.FieldOwner(v1alpha1.FieldManager))
178+
}
179+
180+
func getGiteaToken(ctx context.Context, baseUrl, username, password string) (string, error) {
181+
182+
giteaClient := gitea.NewClientWithHTTP(baseUrl, util.GetHttpClient())
183+
giteaClient.SetBasicAuth(username, password)
184+
giteaClient.SetContext(ctx)
185+
tokens, resp, err := giteaClient.ListAccessTokens(gitea.ListAccessTokensOptions{})
186+
if err != nil {
187+
return "", fmt.Errorf("listing gitea access tokens. stauts: %s error : %w", resp.Status, err)
188+
}
189+
190+
for i := range tokens {
191+
if tokens[i].Name == giteaAdminTokenName {
192+
resp, err := giteaClient.DeleteAccessToken(tokens[i].ID)
193+
if err != nil {
194+
return "", fmt.Errorf("deleting gitea access tokens. stauts: %s error : %w", resp.Status, err)
195+
}
196+
break
197+
}
198+
}
199+
200+
token, resp, err := giteaClient.CreateAccessToken(gitea.CreateAccessTokenOption{
201+
Name: giteaAdminTokenName,
202+
Scopes: []gitea.AccessTokenScope{
203+
gitea.AccessTokenScopeAll,
204+
},
205+
})
206+
if err != nil {
207+
return "", fmt.Errorf("deleting gitea access tokens. stauts: %s error : %w", resp.Status, err)
208+
}
209+
210+
return token.Token, nil
211+
}
212+
126213
func giteaBaseUrl(config util.CorePackageTemplateConfig) string {
127214
return fmt.Sprintf(giteaIngressURL, config.Protocol, config.Port)
128215
}

pkg/util/util.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ package util
33
import (
44
"context"
55
"crypto/rand"
6+
"crypto/tls"
67
"fmt"
78
"math"
89
"math/big"
910
mathrand "math/rand"
11+
"net"
12+
"net/http"
1013
"path/filepath"
1114
"strings"
15+
"time"
1216

1317
"github.com/cnoe-io/idpbuilder/api/v1alpha1"
1418
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -133,3 +137,14 @@ func IsYamlFile(input string) bool {
133137
extension := filepath.Ext(input)
134138
return extension == ".yaml" || extension == ".yml"
135139
}
140+
141+
func GetHttpClient() *http.Client {
142+
tr := &http.Transport{
143+
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
144+
DialContext: (&net.Dialer{
145+
Timeout: 5 * time.Second,
146+
KeepAlive: 30 * time.Second, // from http.DefaultTransport
147+
}).DialContext,
148+
}
149+
return &http.Client{Transport: tr, Timeout: 30 * time.Second}
150+
}

0 commit comments

Comments
 (0)