apply keypair secret

This commit is contained in:
kkb0318
2024-04-10 23:08:23 +09:00
parent 0a81afa3f1
commit 720bc912b9
11 changed files with 149 additions and 59 deletions
+1 -2
View File
@@ -13,7 +13,7 @@ require (
github.com/onsi/ginkgo/v2 v2.17.1
github.com/onsi/gomega v1.30.0
github.com/stretchr/testify v1.9.0
go.uber.org/mock v0.4.0
k8s.io/api v0.29.3
k8s.io/apimachinery v0.29.3
k8s.io/client-go v0.29.3
sigs.k8s.io/controller-runtime v0.17.2
@@ -86,7 +86,6 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.29.3 // indirect
k8s.io/apiextensions-apiserver v0.29.3 // indirect
k8s.io/component-base v0.29.3 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
-2
View File
@@ -137,8 +137,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+24 -7
View File
@@ -27,6 +27,9 @@ import (
irsav1alpha1 "github.com/kkb0318/irsa-manager/api/v1alpha1"
awsclient "github.com/kkb0318/irsa-manager/internal/client"
"github.com/kkb0318/irsa-manager/internal/handler"
"github.com/kkb0318/irsa-manager/internal/kubernetes"
"github.com/kkb0318/irsa-manager/internal/manifests"
"github.com/kkb0318/irsa-manager/internal/selfhosted"
"github.com/kkb0318/irsa-manager/internal/selfhosted/oidc"
)
@@ -53,12 +56,16 @@ type IRSASetupReconciler struct {
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.16.3/pkg/reconcile
func (r *IRSASetupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) {
func (r *IRSASetupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := ctrllog.FromContext(ctx)
obj := &irsav1alpha1.IRSASetup{}
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
kubeClient, err := kubernetes.NewKubernetesClient(r.Client, kubernetes.Owner{Field: "irsa-manager"})
if err != nil {
return ctrl.Result{}, err
}
if !controllerutil.ContainsFinalizer(obj, irsamanagerFinalizer) {
controllerutil.AddFinalizer(obj, irsamanagerFinalizer)
@@ -70,11 +77,11 @@ func (r *IRSASetupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}
if !obj.DeletionTimestamp.IsZero() {
retErr = r.reconcileDelete(ctx, obj)
return
err = r.reconcileDelete(ctx, obj)
return ctrl.Result{}, err
}
if err := r.reconcile(ctx, obj); err != nil {
if err := r.reconcile(ctx, obj, kubeClient); err != nil {
return ctrl.Result{}, err
}
@@ -82,8 +89,8 @@ func (r *IRSASetupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
return ctrl.Result{}, nil
}
func (r *IRSASetupReconciler) reconcile(ctx context.Context, obj *irsav1alpha1.IRSASetup) error {
err := reconcileSelfhosted(ctx, obj, r.AwsClient)
func (r *IRSASetupReconciler) reconcile(ctx context.Context, obj *irsav1alpha1.IRSASetup, kubeClient *kubernetes.KubernetesClient) error {
err := reconcileSelfhosted(ctx, obj, r.AwsClient, kubeClient)
return err
}
@@ -91,7 +98,7 @@ func (r *IRSASetupReconciler) reconcileDelete(ctx context.Context, obj *irsav1al
return nil
}
func reconcileSelfhosted(ctx context.Context, obj *irsav1alpha1.IRSASetup, awsClient awsclient.AwsClient) error {
func reconcileSelfhosted(ctx context.Context, obj *irsav1alpha1.IRSASetup, awsClient awsclient.AwsClient, kubeClient *kubernetes.KubernetesClient) error {
keyPair, err := selfhosted.CreateKeyPair()
if err != nil {
return err
@@ -104,10 +111,20 @@ func reconcileSelfhosted(ctx context.Context, obj *irsav1alpha1.IRSASetup, awsCl
if err != nil {
return err
}
secret, err := manifests.NewSecretBuilder().WithSSHKey(*keyPair).Build("name", "default")
if err != nil {
return err
}
kubeHandler := handler.NewKubernetesHandler(kubeClient)
kubeHandler.Append(secret)
err = selfhosted.Execute(ctx, factory)
if err != nil {
return err
}
err = kubeHandler.ApplyAll(ctx)
if err != nil {
return err
}
return nil
}
+25
View File
@@ -0,0 +1,25 @@
package handler
import (
"context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type KubernetesClient interface {
Apply(ctx context.Context, obj client.Object) error
Delete(ctx context.Context, obj *unstructured.Unstructured, opts DeleteOptions) error
}
// DeleteOptions contains options for delete requests.
type DeleteOptions struct {
// DeletionPropagation decides how the garbage collector will handle the propagation.
DeletionPropagation metav1.DeletionPropagation
// Inclusions determines which in-cluster objects are subject to deletion
// based on the labels.
// A nil Inclusions map means all objects are subject to deletion
Inclusions map[string]string
}
+33
View File
@@ -0,0 +1,33 @@
package handler
import (
"context"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type KubernetesHandler struct {
client KubernetesClient
objs []client.Object
}
func NewKubernetesHandler(k KubernetesClient) *KubernetesHandler {
return &KubernetesHandler{
client: k,
objs: []client.Object{},
}
}
func (k *KubernetesHandler) Append(obj client.Object) {
k.objs = append(k.objs, obj)
}
func (k *KubernetesHandler) ApplyAll(ctx context.Context) error {
for _, obj := range k.objs {
err := k.client.Apply(ctx, obj)
if err != nil {
return err
}
}
return nil
}
+6 -14
View File
@@ -10,22 +10,14 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
)
type Handler struct {
cleanup bool
client client.Client
owner Owner
}
// NewHelper returns an initialized Helper.
func NewHandler(c client.Client, owner Owner, cleanup bool) (*Handler, error) {
return &Handler{
cleanup: cleanup,
client: c,
owner: owner,
func NewKubernetesClient(c client.Client, owner Owner) (*KubernetesClient, error) {
return &KubernetesClient{
client: c,
owner: owner,
}, nil
}
func (h Handler) Apply(ctx context.Context, obj client.Object) error {
func (h KubernetesClient) Apply(ctx context.Context, obj client.Object) error {
opts := []client.PatchOption{
client.ForceOwnership,
client.FieldOwner(h.owner.Field),
@@ -50,7 +42,7 @@ func (h Handler) Apply(ctx context.Context, obj client.Object) error {
return nil
}
func (h Handler) PatchStatus(ctx context.Context, obj client.Object) error {
func (h KubernetesClient) PatchStatus(ctx context.Context, obj client.Object) error {
opts := &client.SubResourcePatchOptions{
PatchOptions: client.PatchOptions{
FieldManager: h.owner.Field,
+11
View File
@@ -0,0 +1,11 @@
package kubernetes
import (
"sigs.k8s.io/controller-runtime/pkg/client"
)
type KubernetesClient struct {
client client.Client
owner Owner
cleanup bool
}
+3 -13
View File
@@ -6,6 +6,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/kkb0318/irsa-manager/internal/handler"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
@@ -13,18 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)
// DeleteOptions contains options for delete requests.
type DeleteOptions struct {
// DeletionPropagation decides how the garbage collector will handle the propagation.
DeletionPropagation metav1.DeletionPropagation
// Inclusions determines which in-cluster objects are subject to deletion
// based on the labels.
// A nil Inclusions map means all objects are subject to deletion
Inclusions map[string]string
}
func (h *Handler) DeleteAll(ctx context.Context, resources []*unstructured.Unstructured, opts DeleteOptions) error {
func (h *KubernetesClient) DeleteAll(ctx context.Context, resources []*unstructured.Unstructured, opts handler.DeleteOptions) error {
if !h.cleanup {
return nil
}
@@ -38,7 +28,7 @@ func (h *Handler) DeleteAll(ctx context.Context, resources []*unstructured.Unstr
}
// Delete deletes the given object (not found errors are ignored).
func (h *Handler) Delete(ctx context.Context, object *unstructured.Unstructured, opts DeleteOptions) error {
func (h *KubernetesClient) Delete(ctx context.Context, object *unstructured.Unstructured, opts handler.DeleteOptions) error {
if !h.cleanup {
return nil
}
-12
View File
@@ -1,12 +0,0 @@
package manifests
import (
"context"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
type Handler interface {
Apply(ctx context.Context, obj *unstructured.Unstructured) error
Delete(ctx context.Context, obj *unstructured.Unstructured) error
}
+46 -1
View File
@@ -1,3 +1,48 @@
package manifests
// TODO: get keys from oidc, and create secret struct
import (
"fmt"
"github.com/kkb0318/irsa-manager/internal/selfhosted"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type SecretBuilder struct {
data map[string][]byte
secretType corev1.SecretType
}
func NewSecretBuilder() *SecretBuilder {
return &SecretBuilder{
secretType: corev1.SecretTypeOpaque,
}
}
func (b *SecretBuilder) WithSSHKey(keyPair selfhosted.KeyPair) *SecretBuilder {
b.data = map[string][]byte{
"ssh-publickey": keyPair.PublicKey(),
corev1.SSHAuthPrivateKey: keyPair.PrivateKey(),
}
b.secretType = corev1.SecretTypeSSHAuth
return b
}
func (b *SecretBuilder) Build(name, ns string) (*corev1.Secret, error) {
if b.data == nil {
return nil, fmt.Errorf("Secret.Data is empty")
}
secret := &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: name,
Namespace: ns,
},
TypeMeta: v1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Secret",
},
Type: b.secretType,
Data: b.data,
}
return secret, nil
}
-8
View File
@@ -1,8 +0,0 @@
package manifests
import "context"
type Manifest interface {
Apply(ctx context.Context, handler Handler) error
Delete(ctx context.Context, handler Handler) error
}