mirror of
https://github.com/storytold/irsa-manager.git
synced 2026-10-20 07:44:48 +00:00
apply keypair secret
This commit is contained in:
@@ -13,7 +13,7 @@ require (
|
|||||||
github.com/onsi/ginkgo/v2 v2.17.1
|
github.com/onsi/ginkgo/v2 v2.17.1
|
||||||
github.com/onsi/gomega v1.30.0
|
github.com/onsi/gomega v1.30.0
|
||||||
github.com/stretchr/testify v1.9.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/apimachinery v0.29.3
|
||||||
k8s.io/client-go v0.29.3
|
k8s.io/client-go v0.29.3
|
||||||
sigs.k8s.io/controller-runtime v0.17.2
|
sigs.k8s.io/controller-runtime v0.17.2
|
||||||
@@ -86,7 +86,6 @@ require (
|
|||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // 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/apiextensions-apiserver v0.29.3 // indirect
|
||||||
k8s.io/component-base v0.29.3 // indirect
|
k8s.io/component-base v0.29.3 // indirect
|
||||||
k8s.io/klog/v2 v2.120.1 // indirect
|
k8s.io/klog/v2 v2.120.1 // indirect
|
||||||
|
|||||||
@@ -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=
|
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 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
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 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ import (
|
|||||||
|
|
||||||
irsav1alpha1 "github.com/kkb0318/irsa-manager/api/v1alpha1"
|
irsav1alpha1 "github.com/kkb0318/irsa-manager/api/v1alpha1"
|
||||||
awsclient "github.com/kkb0318/irsa-manager/internal/client"
|
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"
|
||||||
"github.com/kkb0318/irsa-manager/internal/selfhosted/oidc"
|
"github.com/kkb0318/irsa-manager/internal/selfhosted/oidc"
|
||||||
)
|
)
|
||||||
@@ -53,12 +56,16 @@ type IRSASetupReconciler struct {
|
|||||||
//
|
//
|
||||||
// For more details, check Reconcile and its Result here:
|
// For more details, check Reconcile and its Result here:
|
||||||
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.16.3/pkg/reconcile
|
// - 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)
|
log := ctrllog.FromContext(ctx)
|
||||||
obj := &irsav1alpha1.IRSASetup{}
|
obj := &irsav1alpha1.IRSASetup{}
|
||||||
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
|
if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
|
||||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
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) {
|
if !controllerutil.ContainsFinalizer(obj, irsamanagerFinalizer) {
|
||||||
controllerutil.AddFinalizer(obj, irsamanagerFinalizer)
|
controllerutil.AddFinalizer(obj, irsamanagerFinalizer)
|
||||||
@@ -70,11 +77,11 @@ func (r *IRSASetupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !obj.DeletionTimestamp.IsZero() {
|
if !obj.DeletionTimestamp.IsZero() {
|
||||||
retErr = r.reconcileDelete(ctx, obj)
|
err = r.reconcileDelete(ctx, obj)
|
||||||
return
|
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
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +89,8 @@ func (r *IRSASetupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
|
|||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *IRSASetupReconciler) reconcile(ctx context.Context, obj *irsav1alpha1.IRSASetup) error {
|
func (r *IRSASetupReconciler) reconcile(ctx context.Context, obj *irsav1alpha1.IRSASetup, kubeClient *kubernetes.KubernetesClient) error {
|
||||||
err := reconcileSelfhosted(ctx, obj, r.AwsClient)
|
err := reconcileSelfhosted(ctx, obj, r.AwsClient, kubeClient)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +98,7 @@ func (r *IRSASetupReconciler) reconcileDelete(ctx context.Context, obj *irsav1al
|
|||||||
return nil
|
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()
|
keyPair, err := selfhosted.CreateKeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -104,10 +111,20 @@ func reconcileSelfhosted(ctx context.Context, obj *irsav1alpha1.IRSASetup, awsCl
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
err = selfhosted.Execute(ctx, factory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = kubeHandler.ApplyAll(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -10,22 +10,14 @@ import (
|
|||||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
func NewKubernetesClient(c client.Client, owner Owner) (*KubernetesClient, error) {
|
||||||
cleanup bool
|
return &KubernetesClient{
|
||||||
client client.Client
|
client: c,
|
||||||
owner Owner
|
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,
|
|
||||||
}, nil
|
}, 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{
|
opts := []client.PatchOption{
|
||||||
client.ForceOwnership,
|
client.ForceOwnership,
|
||||||
client.FieldOwner(h.owner.Field),
|
client.FieldOwner(h.owner.Field),
|
||||||
@@ -50,7 +42,7 @@ func (h Handler) Apply(ctx context.Context, obj client.Object) error {
|
|||||||
return nil
|
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{
|
opts := &client.SubResourcePatchOptions{
|
||||||
PatchOptions: client.PatchOptions{
|
PatchOptions: client.PatchOptions{
|
||||||
FieldManager: h.owner.Field,
|
FieldManager: h.owner.Field,
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KubernetesClient struct {
|
||||||
|
client client.Client
|
||||||
|
owner Owner
|
||||||
|
cleanup bool
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
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/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
@@ -13,18 +14,7 @@ import (
|
|||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteOptions contains options for delete requests.
|
func (h *KubernetesClient) DeleteAll(ctx context.Context, resources []*unstructured.Unstructured, opts handler.DeleteOptions) error {
|
||||||
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 {
|
|
||||||
if !h.cleanup {
|
if !h.cleanup {
|
||||||
return nil
|
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).
|
// 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 {
|
if !h.cleanup {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,48 @@
|
|||||||
package manifests
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user