Run kube-cert-agent pod as Concierge ServiceAccount.

Since 0dfb3e95c5, we no longer directly create the kube-cert-agent Pod, so our "use"
permission on PodSecurityPolicies no longer has the intended effect. Since the deployments controller is now the
one creating pods for us, we need to get the permission on the PodSpec of the target pod instead, which we do somewhat
simply by using the same service account as the main Concierge pods.

We still set `automountServiceAccountToken: false`, so this should not actually give any useful permissions to the
agent pod when running.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
Matt Moyer 2021-05-03 16:20:13 -05:00
parent d6a172214d
commit b80cbb8cc5
No known key found for this signature in database
GPG Key ID: EAE88AD172C5AE2D
7 changed files with 26 additions and 1 deletions

View File

@ -47,6 +47,7 @@ data:
impersonationTLSCertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-tls-serving-certificate") @) impersonationTLSCertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-tls-serving-certificate") @)
impersonationCACertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-ca-certificate") @) impersonationCACertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-ca-certificate") @)
impersonationSignerSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-signer-ca-certificate") @) impersonationSignerSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-signer-ca-certificate") @)
serviceAccount: (@= defaultResourceName() @)
labels: (@= json.encode(labels()).rstrip() @) labels: (@= json.encode(labels()).rstrip() @)
kubeCertAgent: kubeCertAgent:
namePrefix: (@= defaultResourceNameWithSuffix("kube-cert-agent-") @) namePrefix: (@= defaultResourceNameWithSuffix("kube-cert-agent-") @)

View File

@ -122,6 +122,9 @@ func validateNames(names *NamesConfigSpec) error {
if names.ImpersonationSignerSecret == "" { if names.ImpersonationSignerSecret == "" {
missingNames = append(missingNames, "impersonationSignerSecret") missingNames = append(missingNames, "impersonationSignerSecret")
} }
if names.ServiceAccount == "" {
missingNames = append(missingNames, "serviceAccount")
}
if len(missingNames) > 0 { if len(missingNames) > 0 {
return constable.Error("missing required names: " + strings.Join(missingNames, ", ")) return constable.Error("missing required names: " + strings.Join(missingNames, ", "))
} }

View File

@ -43,6 +43,7 @@ func TestFromPath(t *testing.T) {
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
labels: labels:
myLabelKey1: myLabelValue1 myLabelKey1: myLabelValue1
myLabelKey2: myLabelValue2 myLabelKey2: myLabelValue2
@ -72,6 +73,7 @@ func TestFromPath(t *testing.T) {
ImpersonationTLSCertificateSecret: "impersonationTLSCertificateSecret-value", ImpersonationTLSCertificateSecret: "impersonationTLSCertificateSecret-value",
ImpersonationCACertificateSecret: "impersonationCACertificateSecret-value", ImpersonationCACertificateSecret: "impersonationCACertificateSecret-value",
ImpersonationSignerSecret: "impersonationSignerSecret-value", ImpersonationSignerSecret: "impersonationSignerSecret-value",
ServiceAccount: "serviceAccount-value",
}, },
Labels: map[string]string{ Labels: map[string]string{
"myLabelKey1": "myLabelValue1", "myLabelKey1": "myLabelValue1",
@ -98,6 +100,7 @@ func TestFromPath(t *testing.T) {
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantConfig: &Config{ wantConfig: &Config{
DiscoveryInfo: DiscoveryInfoSpec{ DiscoveryInfo: DiscoveryInfoSpec{
@ -119,6 +122,7 @@ func TestFromPath(t *testing.T) {
ImpersonationTLSCertificateSecret: "impersonationTLSCertificateSecret-value", ImpersonationTLSCertificateSecret: "impersonationTLSCertificateSecret-value",
ImpersonationCACertificateSecret: "impersonationCACertificateSecret-value", ImpersonationCACertificateSecret: "impersonationCACertificateSecret-value",
ImpersonationSignerSecret: "impersonationSignerSecret-value", ImpersonationSignerSecret: "impersonationSignerSecret-value",
ServiceAccount: "serviceAccount-value",
}, },
Labels: map[string]string{}, Labels: map[string]string{},
KubeCertAgentConfig: KubeCertAgentSpec{ KubeCertAgentConfig: KubeCertAgentSpec{
@ -133,7 +137,7 @@ func TestFromPath(t *testing.T) {
wantError: "validate names: missing required names: servingCertificateSecret, credentialIssuer, " + wantError: "validate names: missing required names: servingCertificateSecret, credentialIssuer, " +
"apiService, impersonationConfigMap, impersonationLoadBalancerService, " + "apiService, impersonationConfigMap, impersonationLoadBalancerService, " +
"impersonationTLSCertificateSecret, impersonationCACertificateSecret, " + "impersonationTLSCertificateSecret, impersonationCACertificateSecret, " +
"impersonationSignerSecret", "impersonationSignerSecret, serviceAccount",
}, },
{ {
name: "Missing apiService name", name: "Missing apiService name",
@ -147,6 +151,7 @@ func TestFromPath(t *testing.T) {
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: apiService", wantError: "validate names: missing required names: apiService",
}, },
@ -162,6 +167,7 @@ func TestFromPath(t *testing.T) {
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: credentialIssuer", wantError: "validate names: missing required names: credentialIssuer",
}, },
@ -177,6 +183,7 @@ func TestFromPath(t *testing.T) {
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: servingCertificateSecret", wantError: "validate names: missing required names: servingCertificateSecret",
}, },
@ -192,6 +199,7 @@ func TestFromPath(t *testing.T) {
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: impersonationConfigMap", wantError: "validate names: missing required names: impersonationConfigMap",
}, },
@ -207,6 +215,7 @@ func TestFromPath(t *testing.T) {
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: impersonationLoadBalancerService", wantError: "validate names: missing required names: impersonationLoadBalancerService",
}, },
@ -222,6 +231,7 @@ func TestFromPath(t *testing.T) {
impersonationLoadBalancerService: impersonationLoadBalancerService-value impersonationLoadBalancerService: impersonationLoadBalancerService-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: impersonationTLSCertificateSecret", wantError: "validate names: missing required names: impersonationTLSCertificateSecret",
}, },
@ -237,6 +247,7 @@ func TestFromPath(t *testing.T) {
impersonationLoadBalancerService: impersonationLoadBalancerService-value impersonationLoadBalancerService: impersonationLoadBalancerService-value
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: impersonationCACertificateSecret", wantError: "validate names: missing required names: impersonationCACertificateSecret",
}, },
@ -252,6 +263,7 @@ func TestFromPath(t *testing.T) {
impersonationLoadBalancerService: impersonationLoadBalancerService-value impersonationLoadBalancerService: impersonationLoadBalancerService-value
impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value impersonationTLSCertificateSecret: impersonationTLSCertificateSecret-value
impersonationCACertificateSecret: impersonationCACertificateSecret-value impersonationCACertificateSecret: impersonationCACertificateSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: impersonationSignerSecret", wantError: "validate names: missing required names: impersonationSignerSecret",
}, },
@ -265,6 +277,7 @@ func TestFromPath(t *testing.T) {
apiService: pinniped-api apiService: pinniped-api
impersonationLoadBalancerService: impersonationLoadBalancerService-value impersonationLoadBalancerService: impersonationLoadBalancerService-value
impersonationSignerSecret: impersonationSignerSecret-value impersonationSignerSecret: impersonationSignerSecret-value
serviceAccount: serviceAccount-value
`), `),
wantError: "validate names: missing required names: impersonationConfigMap, " + wantError: "validate names: missing required names: impersonationConfigMap, " +
"impersonationTLSCertificateSecret, impersonationCACertificateSecret", "impersonationTLSCertificateSecret, impersonationCACertificateSecret",

View File

@ -41,6 +41,7 @@ type NamesConfigSpec struct {
ImpersonationTLSCertificateSecret string `json:"impersonationTLSCertificateSecret"` ImpersonationTLSCertificateSecret string `json:"impersonationTLSCertificateSecret"`
ImpersonationCACertificateSecret string `json:"impersonationCACertificateSecret"` ImpersonationCACertificateSecret string `json:"impersonationCACertificateSecret"`
ImpersonationSignerSecret string `json:"impersonationSignerSecret"` ImpersonationSignerSecret string `json:"impersonationSignerSecret"`
ServiceAccount string `json:"serviceAccount"`
} }
// ServingCertificateConfigSpec contains the configuration knobs for the API's // ServingCertificateConfigSpec contains the configuration knobs for the API's

View File

@ -64,6 +64,9 @@ type AgentConfig struct {
// NamePrefix will be prefixed to all agent pod names. // NamePrefix will be prefixed to all agent pod names.
NamePrefix string NamePrefix string
// ServiceAccountName is the service account under which to run the agent pods.
ServiceAccountName string
// ContainerImagePullSecrets is a list of names of Kubernetes Secret objects that will be used as // ContainerImagePullSecrets is a list of names of Kubernetes Secret objects that will be used as
// ImagePullSecrets on the kube-cert-agent pods. // ImagePullSecrets on the kube-cert-agent pods.
ContainerImagePullSecrets []string ContainerImagePullSecrets []string
@ -472,6 +475,7 @@ func (c *agentController) newAgentDeployment(controllerManagerPod *corev1.Pod) *
RestartPolicy: corev1.RestartPolicyAlways, RestartPolicy: corev1.RestartPolicyAlways,
NodeSelector: controllerManagerPod.Spec.NodeSelector, NodeSelector: controllerManagerPod.Spec.NodeSelector,
AutomountServiceAccountToken: pointer.BoolPtr(false), AutomountServiceAccountToken: pointer.BoolPtr(false),
ServiceAccountName: c.cfg.ServiceAccountName,
NodeName: controllerManagerPod.Spec.NodeName, NodeName: controllerManagerPod.Spec.NodeName,
Tolerations: controllerManagerPod.Spec.Tolerations, Tolerations: controllerManagerPod.Spec.Tolerations,
// We need to run the agent pod as root since the file permissions // We need to run the agent pod as root since the file permissions

View File

@ -123,6 +123,7 @@ func TestAgentController(t *testing.T) {
}}, }},
RestartPolicy: corev1.RestartPolicyAlways, RestartPolicy: corev1.RestartPolicyAlways,
TerminationGracePeriodSeconds: pointer.Int64Ptr(0), TerminationGracePeriodSeconds: pointer.Int64Ptr(0),
ServiceAccountName: "test-service-account-name",
AutomountServiceAccountToken: pointer.BoolPtr(false), AutomountServiceAccountToken: pointer.BoolPtr(false),
SecurityContext: &corev1.PodSecurityContext{ SecurityContext: &corev1.PodSecurityContext{
RunAsUser: pointer.Int64Ptr(0), RunAsUser: pointer.Int64Ptr(0),
@ -672,6 +673,7 @@ func TestAgentController(t *testing.T) {
AgentConfig{ AgentConfig{
Namespace: "concierge", Namespace: "concierge",
ContainerImage: "pinniped-server-image", ContainerImage: "pinniped-server-image",
ServiceAccountName: "test-service-account-name",
NamePrefix: "pinniped-concierge-kube-cert-agent-", NamePrefix: "pinniped-concierge-kube-cert-agent-",
ContainerImagePullSecrets: []string{"pinniped-image-pull-secret"}, ContainerImagePullSecrets: []string{"pinniped-image-pull-secret"},
CredentialIssuerName: "pinniped-concierge-config", CredentialIssuerName: "pinniped-concierge-config",

View File

@ -121,6 +121,7 @@ func PrepareControllers(c *Config) (func(ctx context.Context), error) {
agentConfig := kubecertagent.AgentConfig{ agentConfig := kubecertagent.AgentConfig{
Namespace: c.ServerInstallationInfo.Namespace, Namespace: c.ServerInstallationInfo.Namespace,
ServiceAccountName: c.NamesConfig.ServiceAccount,
ContainerImage: *c.KubeCertAgentConfig.Image, ContainerImage: *c.KubeCertAgentConfig.Image,
NamePrefix: *c.KubeCertAgentConfig.NamePrefix, NamePrefix: *c.KubeCertAgentConfig.NamePrefix,
ContainerImagePullSecrets: c.KubeCertAgentConfig.ImagePullSecrets, ContainerImagePullSecrets: c.KubeCertAgentConfig.ImagePullSecrets,