Skip to content

Commit 0770a47

Browse files
committed
Reduce System Account Coupling
We define a single system account role that is used by (at present) the Kubernetes and Compute services. This has a few drawbacks: first you have to modify identity to enable new functionality in either of those services, and secondly you may inadvertently give away permissions that aren't strictly necessary. What this does is allows each service to define a SystemAccount resource in their own Helm chart, linked to their own role. It also means 3rd party services can define all their own stuff in situ without having to tell the Identity service about itself, or know where the Identity service lives in order to install custom roles. Security wise, anyone who can create a certificate, role and system account can then issue a token to do what they want, so I guess limiting who can do those operations brings security, or perhaps having a PSK to validate the resource is trusted via the PSK. Prior to this a user would have to issue a certificate, create a role (or just reference the uber user one - perhaps we should grant this implicitly via a magical *.* ACL) and modify the identity deployment. So perhaps backward a little bit, but it does offer operational and development benefits.
1 parent 41c96cf commit 0770a47

File tree

9 files changed

+253
-59
lines changed

9 files changed

+253
-59
lines changed

README.md

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,6 @@ providers:
238238
platformAdministrators:
239239
subjects:
240240
241-
systemAccounts:
242-
unikorn-kubernetes: infra-manager-service
243-
unikorn-compute: infra-manager-service
244241
```
245242
246243
Install the Helm repository:
@@ -322,18 +319,13 @@ If your user's email address can be authenticated by any of the supported OIDC i
322319
When using an integration such as the [Unikorn Kubernetes Service](https://github.com/unikorn-cloud/kubernetes) you will need to configure system account to RBAC mappings.
323320
3rd party services usually act on behalf of a user, and as such need elevated global privileges, so as to avoid giving the end user permission to sensitive endpoints.
324321

325-
In the earlier `values.yaml` manifest, the following section was defined:
326-
327-
```yaml
328-
systemAccounts:
329-
unikorn-kubernetes: infra-manager-service
330-
unikorn-compute: infra-manager-service
331-
```
332-
333-
In very simple terms, when you create a 3rd party service, that will need to generate an X.509 certificate in order to authenticate with the tokens endpoint and issue an access token to talk to other Unikorn service APIs.
322+
When you create a 3rd party service, that will need to generate an X.509 certificate in order to authenticate with the tokens endpoint and issue an access token to talk to other Unikorn service APIs.
334323
That certificate will need to be signed by the trusted client CA (typically signed by the `unikorn-client-issuer` managed by cert-manager).
335-
The X.509 Common Name (CN) encoded in the certificate is the key to this mapping e.g. `unikorn-kubernetes`.
336-
The value references a role name that is either installed by default, or created specifically for your service.
324+
The X.509 Common Name (CN) encoded in the certificate is used to lookup a `SystemAccount` resource in any namespace.
325+
The `SystemAccount` resource is then used to lookup a role defined in the same namespace that defines permissions.
326+
327+
The key benefit with this way of defining RBAC rules is that it can be done completely independently of the Identity service.
328+
Care should, however, be taken to ensure only trusted actors are allowed to create roles and system accounts.
337329

338330
#### 3rd Party User RBAC
339331

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.17.3
7+
name: systemaccounts.identity.unikorn-cloud.org
8+
spec:
9+
group: identity.unikorn-cloud.org
10+
names:
11+
categories:
12+
- unikorn
13+
kind: SystemAccount
14+
listKind: SystemAccountList
15+
plural: systemaccounts
16+
singular: systemaccount
17+
scope: Namespaced
18+
versions:
19+
- additionalPrinterColumns:
20+
- jsonPath: .spec.role.name
21+
name: role
22+
type: string
23+
name: v1alpha1
24+
schema:
25+
openAPIV3Schema:
26+
description: |-
27+
SystemAccount is a namespaced resource that defines a system account name
28+
(provided by clients as an X.509 client certificate CN) and a role associated
29+
with that client. This aims to decouple services, and role definitions,
30+
from the identity service itself.
31+
properties:
32+
apiVersion:
33+
description: |-
34+
APIVersion defines the versioned schema of this representation of an object.
35+
Servers should convert recognized schemas to the latest internal value, and
36+
may reject unrecognized values.
37+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
38+
type: string
39+
kind:
40+
description: |-
41+
Kind is a string value representing the REST resource this object represents.
42+
Servers may infer this from the endpoint the client submits requests to.
43+
Cannot be updated.
44+
In CamelCase.
45+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
46+
type: string
47+
metadata:
48+
type: object
49+
spec:
50+
properties:
51+
role:
52+
description: Role is a reference to the role name defined in the local
53+
namespace.
54+
properties:
55+
name:
56+
default: ""
57+
description: |-
58+
Name of the referent.
59+
This field is effectively required, but due to backwards compatibility is
60+
allowed to be empty. Instances of this type with an empty value here are
61+
almost certainly wrong.
62+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
63+
type: string
64+
type: object
65+
x-kubernetes-map-type: atomic
66+
required:
67+
- role
68+
type: object
69+
status:
70+
type: object
71+
required:
72+
- spec
73+
type: object
74+
served: true
75+
storage: true
76+
subresources: {}

charts/identity/templates/identity/clusterrole.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ rules:
1616
- projects
1717
- quotas
1818
- quotametadata
19-
- roles
2019
- serviceaccounts
2120
- users
2221
- organizationusers
@@ -27,6 +26,14 @@ rules:
2726
- patch
2827
- create
2928
- delete
29+
- apiGroups:
30+
- identity.unikorn-cloud.org
31+
resources:
32+
- roles
33+
- systemaccounts
34+
verbs:
35+
- list
36+
- watch
3037
- apiGroups:
3138
- identity.unikorn-cloud.org
3239
resources:

charts/identity/templates/identity/deployment.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ spec:
3434
{{- range $k, $v := .Values.systemAccounts }}
3535
{{- $systemAccounts = append $systemAccounts (printf "%s=%s" $k (include "resource.id" $v)) }}
3636
{{- end }}
37-
- --system-account-roles-ids={{ join "," $systemAccounts }}
3837
{{- with $signup := .Values.signup }}
3938
{{- if $signup.enabled }}
4039
- --user-email-verification

charts/identity/values.yaml

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@ platformAdministrators:
9797
# and not an alias.
9898
subjects: []
9999

100-
# System accounts map X.509 Common Names to roles.
101-
systemAccounts:
102-
unikorn-kubernetes: infra-manager-service
103-
unikorn-compute: infra-manager-service
104-
105100
# A static list of roles.
106101
# Any unscoped API resources are to be managed by the platform operator
107102
# and are assumed to be read only for all. Global permissions are applied
@@ -143,33 +138,6 @@ roles:
143138
compute:clusters: [create,read,update,delete]
144139
application:applications: [create,read,update,delete]
145140
application:applicationsets: [create,read,update,delete]
146-
# An infrastructure manager service is a role primarily for Kubernetes like
147-
# services that can manage identities and physical networks on behalf of a cluster.
148-
infra-manager-service:
149-
decription: Infrastructure manager service
150-
protected: true
151-
scopes:
152-
global:
153-
identity:allocations: [create,read,update,delete]
154-
region:identities: [create,read,delete]
155-
region:regions: [read]
156-
region:regions/detail: [read]
157-
region:flavors: [read]
158-
region:images: [read]
159-
region:externalnetworks: [read]
160-
region:networks: [create,read,delete]
161-
region:servers: [create,read,update,delete]
162-
region:securitygroups: [create,read,update,delete]
163-
# An application manager is a role primarily for the application service that
164-
# needs to be able to see the Kubernetes clusters it's deploying applications
165-
# on to.
166-
application-manager-service:
167-
description: Application manager service
168-
protected: true
169-
scopes:
170-
global:
171-
kubernetes:clusters: [read]
172-
# An administrator can do anything within an organization.
173141
administrator:
174142
description: Organization administrator
175143
scopes:

pkg/apis/unikorn/v1alpha1/register.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ func init() {
6060
SchemeBuilder.Register(&QuotaMetadata{}, &QuotaMetadataList{})
6161
SchemeBuilder.Register(&Quota{}, &QuotaList{})
6262
SchemeBuilder.Register(&Allocation{}, &AllocationList{})
63+
SchemeBuilder.Register(&SystemAccount{}, &SystemAccountList{})
6364
}
6465

6566
// Resource maps a resource type to a group resource.

pkg/apis/unikorn/v1alpha1/types.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package v1alpha1
2020
import (
2121
unikornv1core "github.com/unikorn-cloud/core/pkg/apis/unikorn/v1alpha1"
2222

23+
corev1 "k8s.io/api/core/v1"
2324
"k8s.io/apimachinery/pkg/api/resource"
2425
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2526
)
@@ -516,3 +517,36 @@ type ResourceAllocation struct {
516517

517518
type AllocationStatus struct {
518519
}
520+
521+
// SystemAccountList is a list of system accounts.
522+
// +genclient
523+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
524+
// +kubebuilder:resource:scope=Namespaced,categories=unikorn
525+
type SystemAccountList struct {
526+
metav1.TypeMeta `json:",inline"`
527+
metav1.ListMeta `json:"metadata,omitempty"`
528+
Items []SystemAccount `json:"items"`
529+
}
530+
531+
// SystemAccount is a namespaced resource that defines a system account name
532+
// (provided by clients as an X.509 client certificate CN) and a role associated
533+
// with that client. This aims to decouple services, and role definitions,
534+
// from the identity service itself.
535+
// +genclient
536+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
537+
// +kubebuilder:printcolumn:name="role",type="string",JSONPath=".spec.role.name"
538+
// +kubebuilder:resource:scope=Namespaced,categories=unikorn
539+
type SystemAccount struct {
540+
metav1.TypeMeta `json:",inline"`
541+
metav1.ObjectMeta `json:"metadata,omitempty"`
542+
Spec SystemAccountSpec `json:"spec"`
543+
Status SystemAccountStatus `json:"status,omitempty"`
544+
}
545+
546+
type SystemAccountSpec struct {
547+
// Role is a reference to the role name defined in the local namespace.
548+
Role corev1.LocalObjectReference `json:"role"`
549+
}
550+
551+
type SystemAccountStatus struct {
552+
}

pkg/apis/unikorn/v1alpha1/zz_generated.deepcopy.go

Lines changed: 94 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)