webhook manifests

This commit is contained in:
kkb0318
2024-05-11 16:33:49 +09:00
parent b5427be07d
commit 1358dbf8cf
17 changed files with 514 additions and 318 deletions
@@ -19,6 +19,11 @@ type SecretBuilder struct {
secretType corev1.SecretType
}
type TlsCredential interface {
Certificate() []byte
PrivateKey() []byte
}
func NewSecretBuilder() *SecretBuilder {
return &SecretBuilder{
secretType: corev1.SecretTypeOpaque,
@@ -34,6 +39,15 @@ func (b *SecretBuilder) WithSSHKey(keyPair selfhosted.KeyPair) *SecretBuilder {
return b
}
func (b *SecretBuilder) WithCertificate(t TlsCredential) *SecretBuilder {
b.data = map[string][]byte{
"tls.crt": t.Certificate(),
"tls.key": t.PrivateKey(),
}
b.secretType = corev1.SecretTypeTLS
return b
}
func (b *SecretBuilder) Build(namespacedName types.NamespacedName) (*corev1.Secret, error) {
secret := &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
-10
View File
@@ -1,11 +1 @@
package selfhosted
import (
"sigs.k8s.io/controller-runtime/pkg/client"
)
type WebHook interface {
Resources() []client.Object
Create()
Delete()
}
+9
View File
@@ -0,0 +1,9 @@
package selfhosted
import (
"sigs.k8s.io/controller-runtime/pkg/client"
)
type Webhook interface {
Resources() []client.Object
}
-57
View File
@@ -1,57 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: pod-identity-webhook
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-identity-webhook
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- update
- patch
resourceNames:
- "pod-identity-webhook"
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- get
- watch
- list
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- create
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pod-identity-webhook
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pod-identity-webhook
subjects:
- kind: ServiceAccount
name: pod-identity-webhook
namespace: kube-system
+205 -169
View File
@@ -6,188 +6,224 @@ import (
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
)
var mutatingWebhookConfiguration = v1beta1.MutatingWebhookConfiguration{
TypeMeta: metav1.TypeMeta{
APIVersion: "admissionregistration.k8s.io/v1beta1",
Kind: "MutatingWebhookConfiguration",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-identity-webhook",
Namespace: "kube-system",
},
Webhooks: []v1beta1.MutatingWebhook{
{
Name: "pod-identity-webhook.amazonaws.com",
ClientConfig: v1beta1.WebhookClientConfig{
Service: &v1beta1.ServiceReference{
Name: "pod-identity-webhook",
Namespace: "kube-system",
Path: "/mutate",
},
CABundle: []byte("${CA_BUNDLE}"),
},
Rules: []v1beta1.RuleWithOperations{
{
Operations: []v1beta1.OperationType{"CREATE"},
Rule: v1beta1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods"},
},
},
},
FailurePolicy: (*v1beta1.FailurePolicyType)(nil),
},
},
type baseManifestFactory struct {
deploymentMeta types.NamespacedName
serviceMeta types.NamespacedName
serviceAccountMeta types.NamespacedName
mutatingWebhookConfigurationMeta types.NamespacedName
podLabel map[string]string
}
var deployment = appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "apps/v1",
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
func serviceNamespacedName() types.NamespacedName {
return types.NamespacedName{
Name: "pod-identity-webhook",
Namespace: "kube-system",
},
Spec: appsv1.DeploymentSpec{
Replicas: 1,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": "pod-identity-webhook"},
Namespace: WEBHOOK_NAMESPACE,
}
}
const WEBHOOK_NAMESPACE = "kube-system"
func newBaseManifestFactory() *baseManifestFactory {
return &baseManifestFactory{
deploymentMeta: types.NamespacedName{
Name: "pod-identity-webhook",
Namespace: WEBHOOK_NAMESPACE,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": "pod-identity-webhook"},
},
Spec: corev1.PodSpec{
ServiceAccountName: "pod-identity-webhook",
Containers: []corev1.Container{
serviceMeta: serviceNamespacedName(),
serviceAccountMeta: types.NamespacedName{
Name: "pod-identity-webhook",
Namespace: WEBHOOK_NAMESPACE,
},
mutatingWebhookConfigurationMeta: types.NamespacedName{
Name: "pod-identity-webhook",
Namespace: WEBHOOK_NAMESPACE,
},
podLabel: map[string]string{"app": "pod-identity-webhook"},
}
}
func (b *baseManifestFactory) mutatingWebhookConfiguration() *v1beta1.MutatingWebhookConfiguration {
path := "/mutate"
failurePolicy := v1beta1.Ignore
return &v1beta1.MutatingWebhookConfiguration{
TypeMeta: metav1.TypeMeta{
APIVersion: v1beta1.SchemeGroupVersion.String(),
Kind: "MutatingWebhookConfiguration",
},
ObjectMeta: metav1.ObjectMeta{
Name: b.mutatingWebhookConfigurationMeta.Name,
Namespace: b.mutatingWebhookConfigurationMeta.Namespace,
},
Webhooks: []v1beta1.MutatingWebhook{
{
Name: "pod-identity-webhook.amazonaws.com",
ClientConfig: v1beta1.WebhookClientConfig{
Service: &v1beta1.ServiceReference{
Name: b.serviceMeta.Name,
Namespace: b.serviceMeta.Namespace,
Path: &path,
},
},
Rules: []v1beta1.RuleWithOperations{
{
Name: "pod-identity-webhook",
Image: "quay.io/amis/pod-identity-webhook:v0.0.1",
ImagePullPolicy: corev1.PullAlways,
Command: []string{"/webhook", "--in-cluster", "--namespace=kube-system", "--service-name=pod-identity-webhook", "--tls-secret=pod-identity-webhook", "--annotation-prefix=eks.amazonaws.com", "--token-audience=sts.amazonaws.com", "--logtostderr"},
VolumeMounts: []corev1.VolumeMount{
{
Name: "webhook-certs",
MountPath: "/var/run/app/certs",
ReadOnly: false,
Operations: []v1beta1.OperationType{"CREATE"},
Rule: v1beta1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods"},
},
},
},
FailurePolicy: &failurePolicy,
},
},
}
}
func (b *baseManifestFactory) deployment() *appsv1.Deployment {
replicas := int32(1)
return &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: appsv1.SchemeGroupVersion.String(),
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
Name: b.deploymentMeta.Name,
Namespace: b.deploymentMeta.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: b.podLabel,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: b.podLabel,
},
Spec: corev1.PodSpec{
ServiceAccountName: b.serviceAccountMeta.Name,
Containers: []corev1.Container{
{
Name: "pod-identity-webhook",
Image: "quay.io/amis/pod-identity-webhook:v0.0.1",
ImagePullPolicy: corev1.PullAlways,
// Command: []string{}, // Command must be patched
VolumeMounts: []corev1.VolumeMount{
{
Name: "webhook-certs",
MountPath: "/var/run/app/certs",
ReadOnly: false,
},
},
},
},
Volumes: []corev1.Volume{
{
Name: "webhook-certs",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
},
},
Volumes: []corev1.Volume{
{
Name: "webhook-certs",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
},
},
}
}
func (b *baseManifestFactory) serviceAccount() *corev1.ServiceAccount {
return &corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "ServiceAccount",
},
ObjectMeta: metav1.ObjectMeta{
Name: b.serviceAccountMeta.Name,
Namespace: b.serviceAccountMeta.Namespace,
},
}
}
func (b *baseManifestFactory) clusterRole() *rbacv1.ClusterRole {
return &rbacv1.ClusterRole{
TypeMeta: metav1.TypeMeta{
APIVersion: rbacv1.SchemeGroupVersion.String(),
Kind: "ClusterRole",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-identity-webhook",
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Resources: []string{"secrets"},
Verbs: []string{"create", "get", "update", "patch"},
},
{
APIGroups: []string{""},
Resources: []string{"serviceaccounts"},
Verbs: []string{"get", "watch", "list"},
},
{
APIGroups: []string{"certificates.k8s.io"},
Resources: []string{"certificatesigningrequests"},
Verbs: []string{"create", "get", "list", "watch"},
},
},
}
}
func (b *baseManifestFactory) clusterRoleBinding() *rbacv1.ClusterRoleBinding {
return &rbacv1.ClusterRoleBinding{
TypeMeta: metav1.TypeMeta{
APIVersion: rbacv1.SchemeGroupVersion.String(),
Kind: "ClusterRoleBinding",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-identity-webhook",
},
RoleRef: rbacv1.RoleRef{
APIGroup: rbacv1.SchemeGroupVersion.Group,
Kind: "ClusterRole",
Name: "pod-identity-webhook",
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: b.serviceAccountMeta.Name,
Namespace: b.serviceAccountMeta.Namespace,
},
},
}
}
func (b *baseManifestFactory) service() *corev1.Service {
return &corev1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: b.serviceMeta.Name,
Namespace: b.serviceMeta.Namespace,
Annotations: map[string]string{
"prometheus.io/port": "443",
"prometheus.io/scheme": "https",
"prometheus.io/scrape": "true",
},
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
Port: 443,
TargetPort: intstr.FromInt(443),
},
},
Selector: b.podLabel,
},
},
}
var serviceAccount = corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ServiceAccount",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-identity-webhook",
Namespace: "kube-system",
},
}
type ClusterRole struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Rules []rbacv1.PolicyRule `json:"rules,omitempty"`
}
var clusterRole = ClusterRole{
TypeMeta: metav1.TypeMeta{
APIVersion: "rbac.authorization.k8s.io/v1",
Kind: "ClusterRole",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-identity-webhook",
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Resources: []string{"secrets"},
Verbs: []string{"create", "get", "update", "patch"},
},
{
APIGroups: []string{""},
Resources: []string{"serviceaccounts"},
Verbs: []string{"get", "watch", "list"},
},
{
APIGroups: []string{"certificates.k8s.io"},
Resources: []string{"certificatesigningrequests"},
Verbs: []string{"create", "get", "list", "watch"},
},
},
}
type ClusterRoleBinding struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
RoleRef rbacv1.RoleRef `json:"roleRef"`
Subjects []rbacv1.Subject `json:"subjects"`
}
var clusterRoleBinding = ClusterRoleBinding{
TypeMeta: metav1.TypeMeta{
APIVersion: "rbac.authorization.k8s.io/v1",
Kind: "ClusterRoleBinding",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-identity-webhook",
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: "pod-identity-webhook",
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: "pod-identity-webhook",
Namespace: "kube-system",
},
},
}
var service = corev1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-identity-webhook",
Namespace: "kube-system",
Annotations: map[string]string{
"prometheus.io/port": "443",
"prometheus.io/scheme": "https",
"prometheus.io/scrape": "true",
},
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
Port: 443,
TargetPort: intstr.FromInt(443),
},
},
Selector: map[string]string{
"app": "pod-identity-webhook",
},
},
}
}
@@ -0,0 +1,108 @@
package webhook
import (
"os"
"testing"
"github.com/goccy/go-yaml"
"github.com/stretchr/testify/assert"
"k8s.io/api/admissionregistration/v1beta1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func TestBaseManifests(t *testing.T) {
b := newBaseManifestFactory()
tests := []struct {
name string
runFunc func() client.Object
expected string
expectedFunc func() client.Object
}{
{
name: "mutatingwebhookconfiguration",
runFunc: func() client.Object {
return b.mutatingWebhookConfiguration()
},
expected: "testdata/mutatingwebhook.yaml",
expectedFunc: testMutatingWebhookConfiguration,
},
{
name: "service",
runFunc: func() client.Object {
return b.service()
},
expected: "testdata/service.yaml",
expectedFunc: testService,
},
{
name: "deployment",
runFunc: func() client.Object {
return b.deployment()
},
expected: "testdata/deployment.yaml",
expectedFunc: testDeployment,
},
{
name: "serviceaccount",
runFunc: func() client.Object {
return b.serviceAccount()
},
expected: "testdata/serviceaccount.yaml",
expectedFunc: testServiceAccount,
},
{
name: "clusterrole",
runFunc: func() client.Object {
return b.clusterRole()
},
expected: "testdata/clusterrole.yaml",
expectedFunc: testClusterRole,
},
{
name: "clusterrolebinding",
runFunc: func() client.Object {
return b.clusterRoleBinding()
},
expected: "testdata/clusterrolebinding.yaml",
expectedFunc: testClusterRoleBinding,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actual := tt.runFunc()
data, err := os.ReadFile(tt.expected)
assert.NoError(t, err)
expected := tt.expectedFunc()
err = yaml.UnmarshalWithOptions(data, expected, yaml.UseJSONUnmarshaler())
assert.NoError(t, err)
assert.Equal(t, expected, actual)
})
}
}
func testMutatingWebhookConfiguration() client.Object {
return &v1beta1.MutatingWebhookConfiguration{}
}
func testService() client.Object {
return &corev1.Service{}
}
func testDeployment() client.Object {
return &appsv1.Deployment{}
}
func testServiceAccount() client.Object {
return &corev1.ServiceAccount{}
}
func testClusterRole() client.Object {
return &rbacv1.ClusterRole{}
}
func testClusterRoleBinding() client.Object {
return &rbacv1.ClusterRoleBinding{}
}
+8 -8
View File
@@ -13,30 +13,30 @@ import (
"k8s.io/apimachinery/pkg/types"
)
type TlsCredentials struct {
type TlsCredential struct {
privateKey []byte
certificate []byte
}
func (t *TlsCredentials) CaBundle() string {
func (t TlsCredential) CaBundle() string {
return base64.StdEncoding.EncodeToString(t.certificate)
}
func (t *TlsCredentials) Certificate() []byte {
func (t TlsCredential) Certificate() []byte {
return t.certificate
}
func (t *TlsCredentials) PrivateKey() []byte {
func (t TlsCredential) PrivateKey() []byte {
return t.privateKey
}
func CreateTlsCredential(serviceNamespacedName types.NamespacedName) (TlsCredentials, error) {
func CreateTlsCredential(serviceNamespacedName types.NamespacedName) (TlsCredential, error) {
certificatePeriod := 365 // days
// Generate RSA private key
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return TlsCredentials{}, err
return TlsCredential{}, err
}
// Define certificate template
@@ -56,7 +56,7 @@ func CreateTlsCredential(serviceNamespacedName types.NamespacedName) (TlsCredent
// Create the certificate
certBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
if err != nil {
return TlsCredentials{}, err
return TlsCredential{}, err
}
// Encode the private key to PEM format
@@ -71,5 +71,5 @@ func CreateTlsCredential(serviceNamespacedName types.NamespacedName) (TlsCredent
Bytes: certBytes,
})
return TlsCredentials{privateKey: privPemBytes, certificate: certPemBytes}, nil
return TlsCredential{privateKey: privPemBytes, certificate: certPemBytes}, nil
}
@@ -1,36 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-identity-webhook
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: pod-identity-webhook
template:
metadata:
labels:
app: pod-identity-webhook
spec:
serviceAccountName: pod-identity-webhook
containers:
- name: pod-identity-webhook
image: quay.io/amis/pod-identity-webhook:v0.0.1
imagePullPolicy: Always
command:
- /webhook
- --in-cluster
- --namespace=kube-system
- --service-name=pod-identity-webhook
- --tls-secret=pod-identity-webhook
- --annotation-prefix=eks.amazonaws.com
- --token-audience=sts.amazonaws.com
- --logtostderr
volumeMounts:
- name: webhook-certs
mountPath: /var/run/app/certs
readOnly: false
volumes:
- name: webhook-certs
emptyDir: {}
@@ -1,19 +0,0 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: pod-identity-webhook
namespace: kube-system
webhooks:
- name: pod-identity-webhook.amazonaws.com
failurePolicy: Ignore
clientConfig:
service:
name: pod-identity-webhook
namespace: kube-system
path: "/mutate"
caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURQekNDQWllZ0F3SUJBZ0lVTjVSVnlOTHRhM2pxZkxiS2I5VmFBY0JZaDFnd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0x6RXRNQ3NHQTFVRUF3d2tjRzlrTFdsa1pXNTBhWFI1TFhkbFltaHZiMnN1YTNWaVpTMXplWE4wWlcwdQpjM1pqTUI0WERUSTBNRE13T1RFd016VXlOMW9YRFRJMU1ETXdPVEV3TXpVeU4xb3dMekV0TUNzR0ExVUVBd3drCmNHOWtMV2xrWlc1MGFYUjVMWGRsWW1odmIyc3VhM1ZpWlMxemVYTjBaVzB1YzNaak1JSUJJakFOQmdrcWhraUcKOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXpSYzY0d2V0TzBSVFNOT2V2c3dqd0JpQjZjMFRaKzRubWhYeQpnVEVxNk9MUXZ5R1k4SlBwKzZTZG1qaGFlRGd2SGxmOU1NODNxa2FzdlBzY0Znd0lkOThwQUhwKzhkdEg3RTlNCjZNNCtDZm5LU2V3QmIrQ25YN0lkeGN2Z3hvSE5rMDcvbERhaXJ5TEVTaFprcnphaW9TYW9rb0dIdStaQmhONHYKdVBrK0xiTGVoSW9QUXdYcm9pMHU3dW4yd2NQaExNSENMckZzUzFTQ3pCMm1xdWN1ZFNNOFNOSWpPUGRRVE90VwpNQmNpMmU2MENQTEEzUWVFUkZnbXdzMEVnV3dyc2ZlVjB5ay83SjBTbFJoVStvQWdJajdLSWlxblFjZU54VFl1CmRrMndaL1JDM0wxck40S0xtb1ArS2dWQU9LK3Q4VjlNbVRzVE9pTHJ3WXhnOE14RWVRSURBUUFCbzFNd1VUQWQKQmdOVkhRNEVGZ1FVQzdxOTcxMDk1V3NLdVpFZ0RiRm9SUVZ6M2N3d0h3WURWUjBqQkJnd0ZvQVVDN3E5NzEwOQo1V3NLdVpFZ0RiRm9SUVZ6M2N3d0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DCkFRRUFsOU92Z2Z6eXZSSVFzVXU5ckFMS3psS2FWa0xDTUczczlpblR1c3M1YkRBY2t2cTM3Y04wQzdzd1Q4TU4KTzhNcU9mS3lHa2xSWHZCT1pCZ2tGYmx6U0xPREhORFpnSXZacmYxM2JrK1lCUG5ZOVdyeWVidzFHd0lUWTdNQwo1ZFhyYm9JOWtaOUY1c0NiMzNtYTZFdVhKVlpvS0JFc2U3Z20yckhsOVF4d253NVNrbDFtN2QxeS9nQS9YUll0CmJIbkkzVjlycHpzb0grZzYrdjBxU1Y2dDVHYVpsbW0veFJ5YzNKRmtvaU5xQk44MlVwMTFNUlhjd04wTlpSN2oKZjVEVFJxVHdSKzAzT0I1T1k2R2tyclkrK1IybGdKUk1VNE91aHl2cjhqY1N6Q0tNY2dZMjJkc2d5aThTYjFYMQorL3hUcC80VVpSaU5IQUlGcnlaMFY1RlpvQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
rules:
- operations: [ "CREATE" ]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
@@ -1,19 +0,0 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: pod-identity-webhook
namespace: kube-system
webhooks:
- name: pod-identity-webhook.amazonaws.com
failurePolicy: Ignore
clientConfig:
service:
name: pod-identity-webhook
namespace: kube-system
path: "/mutate"
caBundle: ${CA_BUNDLE}
rules:
- operations: [ "CREATE" ]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
+31
View File
@@ -0,0 +1,31 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-identity-webhook
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- get
- update
- patch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- get
- watch
- list
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- create
- get
- list
- watch
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pod-identity-webhook
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: pod-identity-webhook
subjects:
- kind: ServiceAccount
name: pod-identity-webhook
namespace: kube-system
+36
View File
@@ -0,0 +1,36 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-identity-webhook
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: pod-identity-webhook
template:
metadata:
labels:
app: pod-identity-webhook
spec:
serviceAccountName: pod-identity-webhook
containers:
- name: pod-identity-webhook
image: quay.io/amis/pod-identity-webhook:v0.0.1
imagePullPolicy: Always
# command:
# - /webhook
# - --in-cluster
# - --namespace=kube-system
# - --service-name=pod-identity-webhook
# - --tls-secret=pod-identity-webhook
# - --annotation-prefix=eks.amazonaws.com
# - --token-audience=sts.amazonaws.com
# - --logtostderr
volumeMounts:
- name: webhook-certs
mountPath: /var/run/app/certs
readOnly: false
volumes:
- name: webhook-certs
emptyDir: {}
@@ -0,0 +1,18 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: pod-identity-webhook
namespace: kube-system
webhooks:
- name: pod-identity-webhook.amazonaws.com
failurePolicy: Ignore
clientConfig:
service:
name: pod-identity-webhook
namespace: kube-system
path: "/mutate"
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: pod-identity-webhook
namespace: kube-system
+68
View File
@@ -0,0 +1,68 @@
package webhook
import (
"fmt"
"github.com/kkb0318/irsa-manager/internal/manifests"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type AwsWebhook struct {
resources []client.Object
}
func secretNamespacedName() types.NamespacedName {
return types.NamespacedName{
Name: "pod-identity-webhook",
Namespace: WEBHOOK_NAMESPACE,
}
}
func NewWebHook() (*AwsWebhook, error) {
factory := newBaseManifestFactory()
resources, err := myCertificate(factory)
if err != nil {
return nil, err
}
return &AwsWebhook{resources}, nil
}
func myCertificate(base *baseManifestFactory) ([]client.Object, error) {
tlsCredential, err := CreateTlsCredential(serviceNamespacedName())
if err != nil {
return nil, err
}
resources := []client.Object{}
secretNamespacedName := secretNamespacedName()
secret, err := manifests.NewSecretBuilder().
WithCertificate(tlsCredential).
Build(secretNamespacedName)
if err != nil {
return nil, err
}
deploy := base.deployment()
deploy.Spec.Template.Spec.Containers[0].Command = []string{
"/webhook",
"--in-cluster",
fmt.Sprintf("--namespace=%s", WEBHOOK_NAMESPACE),
fmt.Sprintf("--service-name=%s", base.serviceMeta.Name),
fmt.Sprintf("--tls-secret=%s", secretNamespacedName.Name),
"--annotation-prefix=eks.amazonaws.com",
"--token-audience=sts.amazonaws.com",
"--logtostderr",
}
mutate := base.mutatingWebhookConfiguration()
mutate.Webhooks[0].ClientConfig.CABundle = []byte(tlsCredential.CaBundle())
resources = append(resources,
secret,
deploy,
mutate,
base.clusterRole(),
base.clusterRoleBinding(),
base.serviceAccount(),
base.service(),
)
return resources, nil
}