Skip to content

Commit 76383a3

Browse files
authored
feat: grant permissions to read secrets (#25)
Signed-off-by: Leonardo Cecchi <[email protected]>
1 parent e78aee0 commit 76383a3

File tree

9 files changed

+248
-91
lines changed

9 files changed

+248
-91
lines changed

config/rbac/role.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ kind: ClusterRole
44
metadata:
55
name: plugin-barman-cloud
66
rules:
7+
- apiGroups:
8+
- ""
9+
resources:
10+
- secrets
11+
verbs:
12+
- create
13+
- delete
14+
- get
15+
- list
16+
- watch
717
- apiGroups:
818
- barmancloud.cnpg.io
919
resources:

internal/cnpgi/instance/manager.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import (
77

88
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
99
"github.com/spf13/viper"
10+
corev1 "k8s.io/api/core/v1"
1011
"k8s.io/apimachinery/pkg/fields"
1112
"k8s.io/apimachinery/pkg/runtime"
1213
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
14+
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
1315
ctrl "sigs.k8s.io/controller-runtime"
1416
"sigs.k8s.io/controller-runtime/pkg/cache"
1517
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -23,6 +25,7 @@ var scheme = runtime.NewScheme()
2325
func init() {
2426
utilruntime.Must(barmancloudv1.AddToScheme(scheme))
2527
utilruntime.Must(cnpgv1.AddToScheme(scheme))
28+
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
2629
}
2730

2831
// Start starts the sidecar informers and CNPG-i server
@@ -52,6 +55,13 @@ func Start(ctx context.Context) error {
5255
},
5356
},
5457
},
58+
Client: client.Options{
59+
Cache: &client.CacheOptions{
60+
DisableFor: []client.Object{
61+
&corev1.Secret{},
62+
},
63+
},
64+
},
5565
})
5666
if err != nil {
5767
setupLog.Error(err, "unable to start manager")

internal/cnpgi/instance/wal.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"os"
8+
"path"
89
"strings"
910
"time"
1011

@@ -22,6 +23,13 @@ import (
2223
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
2324
)
2425

26+
const (
27+
// CheckEmptyWalArchiveFile is the name of the file in the PGDATA that,
28+
// if present, requires the WAL archiver to check that the backup object
29+
// store is empty.
30+
CheckEmptyWalArchiveFile = ".check-empty-wal-archive"
31+
)
32+
2533
// WALServiceImplementation is the implementation of the WAL Service
2634
type WALServiceImplementation struct {
2735
BarmanObjectKey client.ObjectKey
@@ -75,11 +83,20 @@ func (w WALServiceImplementation) Archive(
7583
objectStore.Namespace,
7684
&objectStore.Spec.Configuration,
7785
os.Environ())
78-
if apierrors.IsForbidden(err) {
79-
return nil, errors.New("backup credentials don't yet have access permissions. Will retry reconciliation loop")
86+
if err != nil {
87+
if apierrors.IsForbidden(err) {
88+
return nil, errors.New("backup credentials don't yet have access permissions. Will retry reconciliation loop")
89+
}
90+
return nil, err
8091
}
8192

82-
arch, err := archiver.New(ctx, envArchive, w.SpoolDirectory, w.PGDataPath, w.PGWALPath)
93+
arch, err := archiver.New(
94+
ctx,
95+
envArchive,
96+
w.SpoolDirectory,
97+
w.PGDataPath,
98+
path.Join(w.PGDataPath, CheckEmptyWalArchiveFile),
99+
)
83100
if err != nil {
84101
return nil, err
85102
}

internal/cnpgi/operator/reconciler.go

Lines changed: 64 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@ package operator
22

33
import (
44
"context"
5-
"fmt"
65

76
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
87
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/decoder"
98
"github.com/cloudnative-pg/cnpg-i-machinery/pkg/pluginhelper/object"
109
"github.com/cloudnative-pg/cnpg-i/pkg/reconciler"
1110
rbacv1 "k8s.io/api/rbac/v1"
11+
"k8s.io/apimachinery/pkg/api/equality"
1212
apierrs "k8s.io/apimachinery/pkg/api/errors"
13-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1413
ctrl "sigs.k8s.io/controller-runtime"
1514
"sigs.k8s.io/controller-runtime/pkg/client"
15+
"sigs.k8s.io/controller-runtime/pkg/log"
1616

17+
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
1718
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
19+
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/specs"
1820
)
1921

2022
// ReconcilerImplementation implements the Reconciler capability
@@ -45,6 +47,8 @@ func (r ReconcilerImplementation) Pre(
4547
ctx context.Context,
4648
request *reconciler.ReconcilerHooksRequest,
4749
) (*reconciler.ReconcilerHooksResult, error) {
50+
contextLogger := log.FromContext(ctx)
51+
4852
reconciledKind, err := object.GetKind(request.GetResourceDefinition())
4953
if err != nil {
5054
return nil, err
@@ -60,12 +64,28 @@ func (r ReconcilerImplementation) Pre(
6064
return nil, err
6165
}
6266

67+
contextLogger = contextLogger.WithValues("name", cluster.Name, "namespace", cluster.Namespace)
68+
ctx = log.IntoContext(ctx, contextLogger)
69+
6370
pluginConfiguration, err := config.NewFromCluster(cluster)
6471
if err != nil {
6572
return nil, err
6673
}
6774

68-
if err := r.ensureRole(ctx, cluster, pluginConfiguration.BarmanObjectName); err != nil {
75+
var barmanObject barmancloudv1.ObjectStore
76+
if err := r.Client.Get(ctx, client.ObjectKey{
77+
Namespace: cluster.Namespace,
78+
Name: pluginConfiguration.BarmanObjectName,
79+
}, &barmanObject); err != nil {
80+
if apierrs.IsNotFound(err) {
81+
contextLogger.Info("Not found barman object configuration, requeuing")
82+
return &reconciler.ReconcilerHooksResult{
83+
Behavior: reconciler.ReconcilerHooksResult_BEHAVIOR_REQUEUE,
84+
}, nil
85+
}
86+
}
87+
88+
if err := r.ensureRole(ctx, cluster, &barmanObject); err != nil {
6989
return nil, err
7090
}
7191

@@ -91,21 +111,50 @@ func (r ReconcilerImplementation) Post(
91111
func (r ReconcilerImplementation) ensureRole(
92112
ctx context.Context,
93113
cluster *cnpgv1.Cluster,
94-
barmanObjectName string,
114+
barmanObject *barmancloudv1.ObjectStore,
95115
) error {
116+
contextLogger := log.FromContext(ctx)
117+
newRole := specs.BuildRole(cluster, barmanObject)
118+
96119
var role rbacv1.Role
97120
if err := r.Client.Get(ctx, client.ObjectKey{
98-
Namespace: cluster.Namespace,
99-
Name: getRBACName(cluster.Name),
121+
Namespace: newRole.Namespace,
122+
Name: newRole.Name,
100123
}, &role); err != nil {
101-
if apierrs.IsNotFound(err) {
102-
return r.createRole(ctx, cluster, barmanObjectName)
124+
if !apierrs.IsNotFound(err) {
125+
return err
103126
}
104-
return err
127+
128+
contextLogger.Info(
129+
"Creating role",
130+
"name", newRole.Name,
131+
"namespace", newRole.Namespace,
132+
)
133+
134+
if err := ctrl.SetControllerReference(
135+
cluster,
136+
newRole,
137+
r.Client.Scheme(),
138+
); err != nil {
139+
return err
140+
}
141+
142+
return r.Client.Create(ctx, newRole)
105143
}
106144

107-
// TODO: patch existing role
108-
return nil
145+
if equality.Semantic.DeepEqual(newRole.Rules, role.Rules) {
146+
// There's no need to hit the API server again
147+
return nil
148+
}
149+
150+
contextLogger.Info(
151+
"Patching role",
152+
"name", newRole.Name,
153+
"namespace", newRole.Namespace,
154+
"rules", newRole.Rules,
155+
)
156+
157+
return r.Client.Patch(ctx, newRole, client.MergeFrom(&role))
109158
}
110159

111160
func (r ReconcilerImplementation) ensureRoleBinding(
@@ -115,98 +164,26 @@ func (r ReconcilerImplementation) ensureRoleBinding(
115164
var role rbacv1.RoleBinding
116165
if err := r.Client.Get(ctx, client.ObjectKey{
117166
Namespace: cluster.Namespace,
118-
Name: getRBACName(cluster.Name),
167+
Name: specs.GetRBACName(cluster.Name),
119168
}, &role); err != nil {
120169
if apierrs.IsNotFound(err) {
121170
return r.createRoleBinding(ctx, cluster)
122171
}
123172
return err
124173
}
125174

126-
// TODO: patch existing role binding
175+
// TODO: this assumes role bindings never change.
176+
// Is that true? Should we relax this assumption?
127177
return nil
128178
}
129179

130-
func (r ReconcilerImplementation) createRole(
131-
ctx context.Context,
132-
cluster *cnpgv1.Cluster,
133-
barmanObjectName string,
134-
) error {
135-
role := buildRole(cluster, barmanObjectName)
136-
if err := ctrl.SetControllerReference(cluster, role, r.Client.Scheme()); err != nil {
137-
return err
138-
}
139-
return r.Client.Create(ctx, role)
140-
}
141-
142180
func (r ReconcilerImplementation) createRoleBinding(
143181
ctx context.Context,
144182
cluster *cnpgv1.Cluster,
145183
) error {
146-
roleBinding := buildRoleBinding(cluster)
184+
roleBinding := specs.BuildRoleBinding(cluster)
147185
if err := ctrl.SetControllerReference(cluster, roleBinding, r.Client.Scheme()); err != nil {
148186
return err
149187
}
150188
return r.Client.Create(ctx, roleBinding)
151189
}
152-
153-
func buildRole(
154-
cluster *cnpgv1.Cluster,
155-
barmanObjectName string,
156-
) *rbacv1.Role {
157-
return &rbacv1.Role{
158-
ObjectMeta: metav1.ObjectMeta{
159-
Namespace: cluster.Namespace,
160-
Name: getRBACName(cluster.Name),
161-
},
162-
163-
Rules: []rbacv1.PolicyRule{
164-
{
165-
APIGroups: []string{
166-
"barmancloud.cnpg.io",
167-
},
168-
Verbs: []string{
169-
"get",
170-
"watch",
171-
"list",
172-
},
173-
Resources: []string{
174-
"objectstores",
175-
},
176-
ResourceNames: []string{
177-
barmanObjectName,
178-
},
179-
},
180-
},
181-
}
182-
}
183-
184-
func buildRoleBinding(
185-
cluster *cnpgv1.Cluster,
186-
) *rbacv1.RoleBinding {
187-
return &rbacv1.RoleBinding{
188-
ObjectMeta: metav1.ObjectMeta{
189-
Namespace: cluster.Namespace,
190-
Name: getRBACName(cluster.Name),
191-
},
192-
Subjects: []rbacv1.Subject{
193-
{
194-
Kind: "ServiceAccount",
195-
APIGroup: "",
196-
Name: cluster.Name,
197-
Namespace: cluster.Namespace,
198-
},
199-
},
200-
RoleRef: rbacv1.RoleRef{
201-
APIGroup: "rbac.authorization.k8s.io",
202-
Kind: "Role",
203-
Name: getRBACName(cluster.Name),
204-
},
205-
}
206-
}
207-
208-
// getRBACName returns the name of the RBAC entities for the
209-
// barman cloud plugin
210-
func getRBACName(clusterName string) string {
211-
return fmt.Sprintf("%s-barman", clusterName)
212-
}

0 commit comments

Comments
 (0)