Skip to content

Commit d38895e

Browse files
authored
Merge pull request #1287 from rackerlabs/keystone-integration-accounts
feat: add the ability to create Keystone service users
2 parents 05b7fb1 + dcbe96a commit d38895e

File tree

6 files changed

+287
-0
lines changed

6 files changed

+287
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# OpenStack Service Users
2+
3+
Should you need to create service accounts in OpenStack you can do so
4+
by creating a Kubernetes Secret in the `openstack` namespace with
5+
the following labels:
6+
7+
`understack.rackspace.com/keystone-role`:
8+
Defines what this account will have access to do.
9+
10+
`understack.rackspace.com/keystone-user`:
11+
Defines the username in OpenStack Keystone in the `service` domain
12+
which will be created.
13+
14+
Possible roles are:
15+
16+
- `tenant-reader` which allows read access to tenant resources
17+
- `tenant-readwrite` which allows read and write access to tenant resources
18+
- `infra-reader` which allows read access to infrastructure resources
19+
- `infra-readwrite` which allows read and write access to infrastructure resources
20+
21+
Roles can be comma separated.
22+
23+
An example secret would look like:
24+
25+
```yaml
26+
apiVersion: v1
27+
kind: Secret
28+
metadata:
29+
name: mysvc
30+
labels:
31+
understack.rackspace.com/keystone-role: tenant-reader
32+
understack.rackspace.com/keystone-user: mysvc
33+
type: Opaque
34+
dataString:
35+
password: MY_PASSWORD
36+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ nav:
134134
- deploy-guide/config-dex.md
135135
- deploy-guide/config-openstack.md
136136
- deploy-guide/secrets-eso-setup.md
137+
- deploy-guide/openstack-svc-users.md
137138
- deploy-guide/auth.md
138139
- deploy-guide/config-argo-workflows.md
139140
- Starting the Deployment:
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
apiVersion: argoproj.io/v1alpha1
2+
kind: EventSource
3+
metadata:
4+
name: k8s-openstack-secrets
5+
namespace: openstack
6+
spec:
7+
template:
8+
serviceAccountName: k8s-openstack-events-secrets
9+
# Kubernetes resource event sources
10+
resource:
11+
keystone-integration-reader-add:
12+
# monitor deployment resources under openstack namespace
13+
namespace: openstack
14+
group: ""
15+
version: v1
16+
resource: secrets
17+
# Event types to listen for (e.g., ADD, UPDATE, DELETE).
18+
eventTypes:
19+
- ADD
20+
- UPDATE
21+
filter:
22+
labels:
23+
- key: understack.rackspace.com/keystone-role
24+
operation: exists
25+
- key: understack.rackspace.com/keystone-user
26+
operation: exists
27+
keystone-integration-reader-delete:
28+
# monitor deployment resources under openstack namespace
29+
namespace: openstack
30+
group: ""
31+
version: v1
32+
resource: secrets
33+
# Event types to listen for (e.g., ADD, UPDATE, DELETE).
34+
eventTypes:
35+
- DELETE
36+
filter:
37+
labels:
38+
- key: understack.rackspace.com/keystone-user
39+
operation: exists
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
apiVersion: argoproj.io/v1alpha1
3+
kind: Sensor
4+
metadata:
5+
name: keystone-integration-reader-add
6+
namespace: openstack
7+
spec:
8+
template:
9+
serviceAccountName: k8s-openstack-events-secrets
10+
# events the Sensor listens for
11+
dependencies:
12+
- name: secret-dep
13+
eventName: keystone-integration-reader-add
14+
eventSourceName: k8s-openstack-secrets
15+
# actions executed when dependencies are satisfied (StandardK8STrigger designed to create or update a generic Kubernetes resource.)
16+
triggers:
17+
- template:
18+
name: keystone-user-create-update
19+
k8s:
20+
operation: create
21+
source:
22+
resource:
23+
apiVersion: batch/v1
24+
kind: Job
25+
metadata:
26+
generateName: keystone-integration-reader-add-
27+
spec:
28+
ttlSecondsAfterFinished: 600
29+
backoffLimit: 3
30+
template:
31+
spec:
32+
containers:
33+
- name: keystone-user-create-update
34+
image: quay.io/airshipit/heat:2024.2-ubuntu_jammy
35+
command: ["sh", "-c"]
36+
args:
37+
- |
38+
echo "Received Secret Event ${EVENT_TYPE} for ${SECRET_NAME}"
39+
set -x
40+
SVC_ROLES=$(python -c "import json,os; print(json.loads(os.environ.get('LABELS') or '{}').get('understack.rackspace.com/keystone-role',''))")
41+
SVC_USER=$(python -c "import json,os; print(json.loads(os.environ.get('LABELS') or '{}').get('understack.rackspace.com/keystone-user',''))")
42+
SVC_USER=${SVC_USER:-$SECRET_NAME}
43+
PROJ_ID=$(openstack project create --or-show --domain service integration -f value -c id)
44+
SVC_ID=$(openstack user create --or-show --domain service --project "${PROJ_ID}" --description "${SECRET_NAME}" "${SVC_USER}" -f value -c id)
45+
openstack user set --description "${SECRET_NAME}" --project "${PROJ_ID}" "${SVC_ID}"
46+
set +x
47+
svc_pass=$(cat /tmp/user-create/password)
48+
openstack user set --password "${svc_pass}" "${SVC_ID}"
49+
set -x
50+
openstack role add --user "${SVC_ID}" --project "${PROJ_ID}" reader
51+
IFS=','
52+
for svc_role in ${SVC_ROLES}; do
53+
case ${svc_role} in
54+
tenant-reader)
55+
openstack role add --user "${SVC_ID}" --domain default --inherited reader
56+
;;
57+
tenant-readwrite)
58+
openstack role add --user "${SVC_ID}" --domain default --inherited member
59+
;;
60+
infra-reader)
61+
openstack role add --user "${SVC_ID}" --project-domain infra --project baremetal reader
62+
;;
63+
infra-readwrite)
64+
openstack role add --user "${SVC_ID}" --project-domain infra --project baremetal admin
65+
;;
66+
*)
67+
echo "Invalid role ${svc_role}"
68+
;;
69+
esac
70+
done
71+
env:
72+
- name: EVENT_TYPE
73+
value: "placeholder"
74+
- name: SECRET_NAME
75+
value: "placeholder"
76+
- name: LABELS
77+
value: "placeholder"
78+
envFrom:
79+
- secretRef:
80+
name: keystone-keystone-admin
81+
volumeMounts:
82+
- name: user-create
83+
mountPath: /tmp/user-create
84+
volumes:
85+
- name: user-create
86+
secret:
87+
secretName: "placeholder"
88+
restartPolicy: OnFailure
89+
parameters:
90+
- src:
91+
dependencyName: secret-dep
92+
dataKey: body.type
93+
dest: spec.template.spec.containers.0.env.0.value
94+
- src:
95+
dependencyName: secret-dep
96+
dataKey: body.metadata.name
97+
dest: spec.template.spec.containers.0.env.1.value
98+
- src:
99+
dependencyName: secret-dep
100+
dataKey: body.metadata.labels
101+
dest: spec.template.spec.containers.0.env.2.value
102+
- src:
103+
dependencyName: secret-dep
104+
dataKey: body.metadata.name
105+
dest: spec.template.spec.volumes.0.secret.secretName
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
apiVersion: argoproj.io/v1alpha1
3+
kind: Sensor
4+
metadata:
5+
name: keystone-integration-reader-rm
6+
namespace: openstack
7+
spec:
8+
template:
9+
serviceAccountName: k8s-openstack-events-secrets
10+
# events the Sensor listens for
11+
dependencies:
12+
- name: secret-dep
13+
eventName: keystone-integration-reader-delete
14+
eventSourceName: k8s-openstack-secrets
15+
# actions executed when dependencies are satisfied (StandardK8STrigger designed to create or update a generic Kubernetes resource.)
16+
triggers:
17+
- template:
18+
name: keystone-user-delete
19+
k8s:
20+
operation: create
21+
source:
22+
resource:
23+
apiVersion: batch/v1
24+
kind: Job
25+
metadata:
26+
generateName: keystone-integration-reader-rm-
27+
spec:
28+
ttlSecondsAfterFinished: 600
29+
backoffLimit: 3
30+
template:
31+
spec:
32+
containers:
33+
- name: keystone-user-delete
34+
image: quay.io/airshipit/heat:2024.2-ubuntu_jammy
35+
command: ["sh", "-c"]
36+
args:
37+
- |
38+
echo "Received Secret Event ${EVENT_TYPE} for ${SECRET_NAME}"
39+
set -x
40+
SVC_USER=$(python -c "import json,os; print(json.loads(os.environ.get('LABELS') or '{}').get('understack.rackspace.com/keystone-user',''))")
41+
SVC_USER=${SVC_USER:-$SECRET_NAME}
42+
openstack user delete --domain service "${SVC_USER}"
43+
env:
44+
- name: EVENT_TYPE
45+
value: "placeholder"
46+
- name: SECRET_NAME
47+
value: "placeholder"
48+
- name: LABELS
49+
value: "placeholder"
50+
envFrom:
51+
- secretRef:
52+
name: keystone-keystone-admin
53+
restartPolicy: OnFailure
54+
parameters:
55+
- src:
56+
dependencyName: secret-dep
57+
dataKey: body.type
58+
dest: spec.template.spec.containers.0.env.0.value
59+
- src:
60+
dependencyName: secret-dep
61+
dataKey: body.metadata.name
62+
dest: spec.template.spec.containers.0.env.1.value
63+
- src:
64+
dependencyName: secret-dep
65+
dataKey: body.metadata.labels
66+
dest: spec.template.spec.containers.0.env.2.value
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
apiVersion: v1
3+
kind: ServiceAccount
4+
metadata:
5+
namespace: openstack
6+
name: k8s-openstack-events-secrets
7+
---
8+
apiVersion: rbac.authorization.k8s.io/v1
9+
kind: Role
10+
metadata:
11+
namespace: openstack
12+
name: k8s-openstack-events-secrets
13+
rules:
14+
- apiGroups:
15+
- ""
16+
resources:
17+
- secrets
18+
verbs:
19+
- list
20+
- watch
21+
- apiGroups:
22+
- batch
23+
resources:
24+
- jobs
25+
verbs:
26+
- create
27+
---
28+
apiVersion: rbac.authorization.k8s.io/v1
29+
kind: RoleBinding
30+
metadata:
31+
namespace: openstack
32+
name: k8s-openstack-events-secrets
33+
roleRef:
34+
apiGroup: rbac.authorization.k8s.io
35+
kind: Role
36+
name: k8s-openstack-events-secrets
37+
subjects:
38+
- kind: ServiceAccount
39+
name: k8s-openstack-events-secrets
40+
namespace: openstack

0 commit comments

Comments
 (0)