Skip to content

Commit a67b7b0

Browse files
authored
Remove ability to grant teams access to quay repos based on config map (#279)
STONEBLD-4522 Signed-off-by: Robert Cerven <rcerven@redhat.com>
1 parent c908c53 commit a67b7b0

8 files changed

Lines changed: 4 additions & 911 deletions

cmd/main.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -240,16 +240,6 @@ func main() {
240240
os.Exit(1)
241241
}
242242

243-
if err = (&controllers.QuayUsersConfigMapReconciler{
244-
Client: mgr.GetClient(),
245-
Scheme: mgr.GetScheme(),
246-
BuildQuayClient: buildQuayClientFunc,
247-
QuayOrganization: quayOrganization,
248-
}).SetupWithManager(mgr); err != nil {
249-
setupLog.Error(err, "unable to create controller", "controller", "ConfigMap")
250-
os.Exit(1)
251-
}
252-
253243
if err = (&controllers.ApplicationPullSecretCreator{
254244
Client: mgr.GetClient(),
255245
Scheme: mgr.GetScheme(),

config/rbac/role.yaml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@ rules:
88
- ""
99
resources:
1010
- configmaps
11-
verbs:
12-
- get
13-
- list
14-
- update
15-
- watch
16-
- apiGroups:
17-
- ""
18-
resources:
1911
- namespaces
2012
verbs:
2113
- get

internal/controller/imagerepository_controller.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ const (
4949
ImageRepositoryFinalizer = "appstudio.openshift.io/image-repository"
5050

5151
updateComponentAnnotationName = "image-controller.appstudio.redhat.com/update-component-image"
52-
additionalUsersConfigMapName = "image-controller-additional-users"
53-
additionalUsersConfigMapKey = "quay.io"
5452
skipRepositoryDeletionAnnotationName = "image-controller.appstudio.redhat.com/skip-repository-deletion"
5553

5654
waitForRelatedComponentInitialDelay = 5
@@ -573,10 +571,6 @@ func (r *ImageRepositoryReconciler) ProvisionImageRepository(ctx context.Context
573571
return err
574572
}
575573

576-
if err = r.GrantRepositoryAccessToTeam(ctx, imageRepository); err != nil {
577-
return err
578-
}
579-
580574
var notificationStatus []imagerepositoryv1alpha1.NotificationStatus
581575
if notificationStatus, err = r.SetNotifications(ctx, imageRepository); err != nil {
582576
return err
@@ -666,46 +660,6 @@ func (r *ImageRepositoryReconciler) ProvisionImageRepositoryAccess(ctx context.C
666660
return data, nil
667661
}
668662

669-
// GrantRepositoryAccessToTeam will add additional repository access to team, based on config map
670-
func (r *ImageRepositoryReconciler) GrantRepositoryAccessToTeam(ctx context.Context, imageRepository *imagerepositoryv1alpha1.ImageRepository) error {
671-
log := ctrllog.FromContext(ctx).WithName("GrantAdditionalRepositoryAccessToTeam")
672-
673-
additionalUsersConfigMap := &corev1.ConfigMap{}
674-
if err := r.Client.Get(ctx, types.NamespacedName{Name: additionalUsersConfigMapName, Namespace: imageRepository.Namespace}, additionalUsersConfigMap); err != nil {
675-
if errors.IsNotFound(err) {
676-
log.Info("Config map with additional users doesn't exist", "ConfigMapName", additionalUsersConfigMapName, l.Action, l.ActionView)
677-
return nil
678-
}
679-
log.Error(err, "failed to read config map with additional users", "ConfigMapName", additionalUsersConfigMapName, l.Action, l.ActionView)
680-
return err
681-
}
682-
_, usersExist := additionalUsersConfigMap.Data[additionalUsersConfigMapKey]
683-
if !usersExist {
684-
log.Info("Config map with additional users doesn't have the key", "ConfigMapName", additionalUsersConfigMapName, "ConfigMapKey", additionalUsersConfigMapKey, l.Action, l.ActionView)
685-
return nil
686-
}
687-
688-
imageRepositoryName := imageRepository.Spec.Image.Name
689-
teamName := getQuayTeamName(imageRepository.Namespace)
690-
691-
// get team, if team doesn't exist it will be created, we don't care about users as that will be taken care of by config map controller
692-
// so in this case if config map exists, team already exists as well with appropriate users
693-
log.Info("Ensure team", "TeamName", teamName)
694-
if _, err := r.QuayClient.EnsureTeam(r.QuayOrganization, teamName); err != nil {
695-
log.Error(err, "failed to get or create team", "TeamName", teamName, l.Action, l.ActionView)
696-
return err
697-
}
698-
699-
// add repo permission to the team
700-
log.Info("Adding repository permission to the team", "TeamName", teamName, "RepositoryName", imageRepositoryName)
701-
if err := r.QuayClient.AddReadPermissionsForRepositoryToTeam(r.QuayOrganization, imageRepositoryName, teamName); err != nil {
702-
log.Error(err, "failed to grant repo permission to the team", "TeamName", teamName, "RepositoryName", imageRepositoryName, l.Action, l.ActionAdd)
703-
return err
704-
}
705-
706-
return nil
707-
}
708-
709663
// RegenerateImageRepositoryCredentials rotates robot account(s) token and updates corresponding secret(s)
710664
func (r *ImageRepositoryReconciler) RegenerateImageRepositoryCredentials(ctx context.Context, imageRepository *imagerepositoryv1alpha1.ImageRepository) error {
711665
log := ctrllog.FromContext(ctx)

internal/controller/imagerepository_controller_test.go

Lines changed: 4 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ var _ = Describe("Image repository controller", func() {
463463
}, timeout, interval).WithTimeout(ensureTimeout).Should(BeTrue())
464464
})
465465

466-
assertProvisionRepository := func(updateComponentAnnotation, grantRepoPermission, setNotification bool) {
466+
assertProvisionRepository := func(updateComponentAnnotation, setNotification bool) {
467467
quay.RepositoryExistsFunc = func(organization, imageRepository string) (bool, error) {
468468
return true, nil
469469
}
@@ -503,6 +503,7 @@ var _ = Describe("Image repository controller", func() {
503503
defer GinkgoRecover()
504504
Expect(organization).To(Equal(quay.TestQuayOrg))
505505
Expect(imageRepository).To(Equal(expectedImageName))
506+
Expect(isRobot).To(BeTrue())
506507
if strings.HasPrefix(accountName, expectedRobotAccountPrefix) || accountName == expectedNamespaceRobotAccountName {
507508
if strings.HasPrefix(accountName, expectedRobotAccountPrefix) {
508509
// method is called for pull or push robot account
@@ -524,27 +525,6 @@ var _ = Describe("Image repository controller", func() {
524525
}
525526
return nil
526527
}
527-
isEnsureTeamInvoked := false
528-
isAddReadPermissionsForRepositoryToTeamInvoked := false
529-
if grantRepoPermission {
530-
quay.EnsureTeamFunc = func(organization, teamName string) ([]quay.Member, error) {
531-
defer GinkgoRecover()
532-
Expect(organization).To(Equal(quay.TestQuayOrg))
533-
expectedTeamName := getQuayTeamName(resourceKey.Namespace)
534-
Expect(teamName).To(Equal(expectedTeamName))
535-
isEnsureTeamInvoked = true
536-
return nil, nil
537-
}
538-
quay.AddReadPermissionsForRepositoryToTeamFunc = func(organization, imageRepository, teamName string) error {
539-
defer GinkgoRecover()
540-
Expect(organization).To(Equal(quay.TestQuayOrg))
541-
Expect(imageRepository).To(Equal(expectedImageName))
542-
expectedTeamName := getQuayTeamName(resourceKey.Namespace)
543-
Expect(teamName).To(Equal(expectedTeamName))
544-
isAddReadPermissionsForRepositoryToTeamInvoked = true
545-
return nil
546-
}
547-
}
548528
isCreateNotificationInvoked := false
549529
isGetNotificationsInvoked := false
550530
if setNotification {
@@ -618,11 +598,6 @@ var _ = Describe("Image repository controller", func() {
618598
}
619599
Eventually(func() bool { return isGetRobotAccountInvoked }, timeout, interval).Should(BeTrue())
620600

621-
if grantRepoPermission {
622-
Eventually(func() bool { return isEnsureTeamInvoked }, timeout, interval).Should(BeTrue())
623-
Eventually(func() bool { return isAddReadPermissionsForRepositoryToTeamInvoked }, timeout, interval).Should(BeTrue())
624-
}
625-
626601
waitImageRepositoryFinalizerOnImageRepository(resourceKey)
627602

628603
component := getComponent(componentKey)
@@ -720,7 +695,7 @@ var _ = Describe("Image repository controller", func() {
720695
}
721696

722697
It("should provision image repository for component, without update component annotation", func() {
723-
assertProvisionRepository(false, false, true)
698+
assertProvisionRepository(false, true)
724699

725700
quay.DeleteRobotAccountFunc = func(organization, robotAccountName string) (bool, error) {
726701
return true, nil
@@ -733,67 +708,8 @@ var _ = Describe("Image repository controller", func() {
733708
assertSecretsGoneFromServiceAccounts()
734709
})
735710

736-
It("should provision image repository for component, with update component annotation and grant permission to team", func() {
737-
usersConfigMapKey := types.NamespacedName{Name: additionalUsersConfigMapName, Namespace: resourceKey.Namespace}
738-
expectedTeamName := getQuayTeamName(resourceKey.Namespace)
739-
isEnsureTeamInvoked := false
740-
isListRepositoryPermissionsForTeamInvoked := false
741-
countAddUserToTeamInvoked := 0
742-
isDeleteTeamInvoked := false
743-
744-
quay.EnsureTeamFunc = func(organization, teamName string) ([]quay.Member, error) {
745-
defer GinkgoRecover()
746-
Expect(organization).To(Equal(quay.TestQuayOrg))
747-
Expect(teamName).To(Equal(expectedTeamName))
748-
isEnsureTeamInvoked = true
749-
return []quay.Member{}, nil
750-
}
751-
quay.ListRepositoryPermissionsForTeamFunc = func(organization, teamName string) ([]quay.TeamPermission, error) {
752-
defer GinkgoRecover()
753-
Expect(organization).To(Equal(quay.TestQuayOrg))
754-
Expect(teamName).To(Equal(expectedTeamName))
755-
isListRepositoryPermissionsForTeamInvoked = true
756-
return []quay.TeamPermission{}, nil
757-
}
758-
quay.AddUserToTeamFunc = func(organization, teamName, userName string) (bool, error) {
759-
defer GinkgoRecover()
760-
Expect(organization).To(Equal(quay.TestQuayOrg))
761-
Expect(teamName).To(Equal(expectedTeamName))
762-
Expect(userName).To(BeElementOf([]string{"user1", "user2"}))
763-
countAddUserToTeamInvoked++
764-
return false, nil
765-
}
766-
767-
createUsersConfigMap(usersConfigMapKey, []string{"user1", "user2"})
768-
Eventually(func() bool { return isEnsureTeamInvoked }, timeout, interval).Should(BeTrue())
769-
Eventually(func() bool { return isListRepositoryPermissionsForTeamInvoked }, timeout, interval).Should(BeTrue())
770-
Eventually(func() int { return countAddUserToTeamInvoked }, timeout, interval).Should(Equal(2))
771-
waitQuayTeamUsersFinalizerOnConfigMap(usersConfigMapKey)
772-
773-
assertProvisionRepository(true, true, true)
774-
775-
quay.DeleteTeamFunc = func(organization, teamName string) error {
776-
defer GinkgoRecover()
777-
Expect(organization).To(Equal(quay.TestQuayOrg))
778-
Expect(teamName).To(Equal(expectedTeamName))
779-
isDeleteTeamInvoked = true
780-
return nil
781-
}
782-
deleteUsersConfigMap(usersConfigMapKey)
783-
Eventually(func() bool { return isDeleteTeamInvoked }, timeout, interval).Should(BeTrue())
784-
785-
quay.DeleteRobotAccountFunc = func(organization, robotAccountName string) (bool, error) {
786-
return true, nil
787-
}
788-
quay.DeleteRepositoryFunc = func(organization, imageRepository string) (bool, error) {
789-
return true, nil
790-
}
791-
deleteImageRepository(resourceKey)
792-
assertSecretsGoneFromServiceAccounts()
793-
})
794-
795711
It("should provision image repository for component, with update component annotation", func() {
796-
assertProvisionRepository(true, false, false)
712+
assertProvisionRepository(true, false)
797713
})
798714

799715
It("should regenerate pull & push tokens and create pull && push secrets when they don't exist", func() {

internal/controller/suite_test.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,6 @@ var _ = BeforeSuite(func() {
117117
}).SetupWithManager(k8sManager)
118118
Expect(err).ToNot(HaveOccurred())
119119

120-
err = (&QuayUsersConfigMapReconciler{
121-
Client: k8sManager.GetClient(),
122-
Scheme: k8sManager.GetScheme(),
123-
BuildQuayClient: func() (quay.QuayService, error) { return quay.TestQuayClient{}, nil },
124-
QuayOrganization: quay.TestQuayOrg,
125-
}).SetupWithManager(k8sManager)
126-
Expect(err).ToNot(HaveOccurred())
127-
128120
err = (&ApplicationPullSecretCreator{
129121
Client: k8sManager.GetClient(),
130122
Scheme: k8sManager.GetScheme(),

internal/controller/suite_util_test.go

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"encoding/base64"
2121
"encoding/json"
2222
"fmt"
23-
"strings"
2423
"time"
2524

2625
. "github.com/onsi/ginkgo/v2"
@@ -371,22 +370,6 @@ func getNamespace(name string) corev1.Namespace {
371370
return ns
372371
}
373372

374-
func deleteNamespace(name string) {
375-
namespace := corev1.Namespace{
376-
TypeMeta: metav1.TypeMeta{
377-
APIVersion: "v1",
378-
Kind: "Namespace",
379-
},
380-
ObjectMeta: metav1.ObjectMeta{
381-
Name: name,
382-
},
383-
}
384-
385-
if err := k8sClient.Delete(ctx, &namespace); err != nil && !k8sErrors.IsNotFound(err) {
386-
Fail(err.Error())
387-
}
388-
}
389-
390373
func waitSecretExist(secretKey types.NamespacedName) *corev1.Secret {
391374
secret := &corev1.Secret{}
392375
Eventually(func() bool {
@@ -482,65 +465,6 @@ func deleteServiceAccount(serviceAccountKey types.NamespacedName) {
482465
}, timeout, interval).Should(BeTrue())
483466
}
484467

485-
func createUsersConfigMap(configMapKey types.NamespacedName, users []string) {
486-
configMapData := map[string]string{}
487-
configMapData[additionalUsersConfigMapKey] = strings.Join(users, " ")
488-
489-
usersConfigMap := corev1.ConfigMap{
490-
ObjectMeta: metav1.ObjectMeta{Name: configMapKey.Name, Namespace: configMapKey.Namespace},
491-
Data: configMapData,
492-
}
493-
494-
if err := k8sClient.Create(ctx, &usersConfigMap); err != nil && !k8sErrors.IsAlreadyExists(err) {
495-
Fail(err.Error())
496-
}
497-
}
498-
499-
func deleteUsersConfigMap(configMapKey types.NamespacedName) {
500-
usersConfigMap := corev1.ConfigMap{}
501-
if err := k8sClient.Get(ctx, configMapKey, &usersConfigMap); err != nil {
502-
if k8sErrors.IsNotFound(err) {
503-
return
504-
}
505-
Fail(err.Error())
506-
}
507-
if err := k8sClient.Delete(ctx, &usersConfigMap); err != nil && !k8sErrors.IsNotFound(err) {
508-
Fail(err.Error())
509-
}
510-
Eventually(func() bool {
511-
return k8sErrors.IsNotFound(k8sClient.Get(ctx, configMapKey, &usersConfigMap))
512-
}, timeout, interval).Should(BeTrue())
513-
}
514-
515-
func addUsersToUsersConfigMap(configMapKey types.NamespacedName, addUsers []string) {
516-
usersConfigMap := corev1.ConfigMap{}
517-
Eventually(func() bool {
518-
Expect(k8sClient.Get(ctx, configMapKey, &usersConfigMap)).Should(Succeed())
519-
return usersConfigMap.ResourceVersion != ""
520-
}, timeout, interval).Should(BeTrue())
521-
522-
currentUsers, usersExist := usersConfigMap.Data[additionalUsersConfigMapKey]
523-
if !usersExist {
524-
Fail("users config map is missing key")
525-
}
526-
527-
newUsers := strings.Join(addUsers, " ")
528-
allUsers := fmt.Sprintf("%s %s", currentUsers, newUsers)
529-
usersConfigMap.Data[additionalUsersConfigMapKey] = allUsers
530-
531-
Expect(k8sClient.Update(ctx, &usersConfigMap)).Should(Succeed())
532-
}
533-
534-
func waitQuayTeamUsersFinalizerOnConfigMap(usersConfigMapKey types.NamespacedName) {
535-
usersConfigMap := &corev1.ConfigMap{}
536-
Eventually(func() bool {
537-
if err := k8sClient.Get(ctx, usersConfigMapKey, usersConfigMap); err != nil {
538-
return false
539-
}
540-
return controllerutil.ContainsFinalizer(usersConfigMap, ConfigMapFinalizer)
541-
}, timeout, interval).Should(BeTrue())
542-
}
543-
544468
func verifySecretAuth(secretDockerconfigJson, expectedImage, robotAccountName, token string) {
545469
var authDataJson dockerConfigJson
546470
Expect(json.Unmarshal([]byte(secretDockerconfigJson), &authDataJson)).To(Succeed())

0 commit comments

Comments
 (0)