Skip to content

Commit dfc0901

Browse files
[v16] helm: Add support for jamf_service to the teleport-kube-agent Helm chart (#42604)
* Add jamf_service support to the Helm chart * Add tests for jamf_service * Remove unnecessary comments * Update README * Update values schema * Update docs * Commit missing lint files * Update test snapshots * Fix Secret tests * Update docs * Add support for Jamf API Client Credentials * Update snapshots * Unify Jamf password/Client Secret into jamfSecret key in Secret * Update snapshots * Add lint files * Update docs * Update image version in tests * Add words to a dictionary * Apply suggestions from code review Co-authored-by: Hugo Shaka <hugo.hervieux@goteleport.com> * Drop support for Jamf username and password auth * Update image tags --------- Co-authored-by: Hugo Shaka <hugo.hervieux@goteleport.com>
1 parent 33e4b93 commit dfc0901

21 files changed

+933
-47
lines changed

docs/cspell.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@
514514
"ioreg",
515515
"isnt",
516516
"isrgrootx",
517+
"jamfapiendpoint",
518+
"jamfclientid",
517519
"javapipeline",
518520
"jetbrains",
519521
"jiraapitoken",

docs/pages/reference/helm-reference/includes/zz_generated.teleport-kube-agent.mdx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ when running the `teleport-kube-agent` chart.
1414
| Teleport Application service | `app` | [`apps`](#apps) or [`appResources`](#appresources) |
1515
| Teleport Database service | `db` | [`databases`](#databases) or [`databaseResources`](#databaseresources) |
1616
| Teleport Discovery service | `discovery` | [`kubeClusterName`](#kubeclustername) |
17+
| Teleport Jamf service | `jamf` | [`jamfApiEndpoint`](#jamfapiendpoint), [`jamfClientId`](#jamfclientid) |
1718

1819
For example:
1920
```yaml
@@ -454,6 +455,85 @@ kubernetesDiscovery:
454455
env: testing
455456
```
456457

458+
## `jamfApiEndpoint`
459+
460+
| Type | Default |
461+
|------|---------|
462+
| `string` | `""` |
463+
464+
`jamfApiEndpoint` sets the Jamf Pro API endpoint used for Jamf service.
465+
Example: "https://yourtenant.jamfcloud.com/api".
466+
467+
This setting is required if the chart `roles` contains `jamf`.
468+
469+
## `jamfClientId`
470+
471+
| Type | Default |
472+
|------|---------|
473+
| `string` | `""` |
474+
475+
`jamfClientId` sets the Jamf Pro API Client ID used for Jamf service.
476+
477+
This setting is required if the chart `roles` contains `jamf`.
478+
479+
## `jamfClientSecret`
480+
481+
| Type | Default |
482+
|------|---------|
483+
| `string` | `""` |
484+
485+
`jamfClientSecret` sets the Jamf Pro API client secret used for Jamf service.
486+
487+
This setting is required if the chart `roles` contains `jamf` and `jamfCredentialsSecret.create` is set to `true`.
488+
If you provide your own Kubernetes Secret, this setting can remain unset.
489+
490+
## `jamfCredentialsSecret`
491+
492+
`jamfCredentialsSecret` manages the Kubernetes Secret containing the Jamf API credentials (either Jamf client secret or password).
493+
494+
### `jamfCredentialsSecret.create`
495+
496+
| Type | Default |
497+
|------|---------|
498+
| `bool` | `true` |
499+
500+
`jamfCredentialsSecret.create` controls whether the chart creates the
501+
Kubernetes `Secret` containing the Jamf Pro API Client Secret.
502+
If false, you must create a Kubernetes Secret with the configured name in
503+
the Helm release namespace.
504+
505+
### `jamfCredentialsSecret.name`
506+
507+
| Type | Default |
508+
|------|---------|
509+
| `string` | `"teleport-jamf-api-credentials"` |
510+
511+
`jamfCredentialsSecret.name` is the name of the Kubernetes Secret
512+
containing the Jamf Pro API Client Secret used by the chart.
513+
514+
If `jamfCredentialsSecret.create` is `false`, the chart will not attempt to create the secret itself.
515+
Instead, it will read the value from an existing Kubernetes Secret. `jamfCredentialsSecret.name`
516+
configures the name of this secret. This allows you to configure this secret externally and avoid having a plaintext
517+
Jamf Pro API Client Secret stored in your Teleport chart values.
518+
519+
To create your own Kubernetes Secret containing Jamf Pro API Client Secret, run the command:
520+
521+
```code
522+
$ kubectl --namespace teleport create secret generic my-jamf-secret --from-literal=credential=<replace-with-actual-secret>
523+
```
524+
525+
<Admonition type="note">
526+
The key used for the Jamf Pro API Client Secret inside the secret must be `credential`, as in the command above.
527+
</Admonition>
528+
529+
For example:
530+
531+
```yaml
532+
jamfCredentialsSecret:
533+
create: false
534+
name: my-jamf-secret
535+
```
536+
457537
## `teleportVersionOverride`
458538

459539
| Type | Default |

docs/pages/reference/helm-reference/teleport-kube-agent.mdx

Lines changed: 27 additions & 25 deletions
Large diffs are not rendered by default.

examples/chart/teleport-kube-agent/.lint/all-v6.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
authToken: auth-token
22
proxyAddr: proxy.example.com:3080
3-
roles: kube,app,db
3+
roles: kube,app,db,jamf
44
kubeClusterName: test-kube-cluster-name
55
labels:
66
cluster: testing
@@ -15,6 +15,9 @@ databases:
1515
protocol: "postgres"
1616
labels:
1717
database: staging
18+
jamfApiEndpoint: "testjamf.jamfcloud.com/api"
19+
jamfClientId: teleport-jamf-client-id
20+
jamfClientSecret: secret-jamf-client-secret
1821
annotations:
1922
config:
2023
kubernetes.io/config: "test-annotation"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
authToken: auth-token
2+
proxyAddr: proxy.example.com:3080
3+
roles: jamf
4+
jamfApiEndpoint: "https://testjamf.jamfcloud.com/api"
5+
jamfClientId: teleport-jamf-client-id
6+
jamfCredentialsSecret:
7+
create: false
8+
name: existing-teleport-jamf-secret
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
authToken: auth-token
2+
proxyAddr: proxy.example.com:3080
3+
roles: jamf
4+
jamfApiEndpoint: "https://testjamf.jamfcloud.com/api"
5+
jamfClientId: teleport-jamf-client-id
6+
jamfClientSecret: secret-jamf-client-secret

examples/chart/teleport-kube-agent/README.md

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ with an existing Teleport cluster:
66
- Teleport Application access
77
- Teleport Database access
88
- Teleport Kubernetes App Discovery
9+
- Teleport Jamf service
910

1011
To use it, you will need:
1112
- an existing Teleport cluster (at least proxy and auth services)
@@ -133,14 +134,14 @@ Set the values in the above command as appropriate for your setup.
133134

134135
These are the supported values for the `apps` map:
135136

136-
| Key | Description | Example | Default | Required |
137-
| --- | --- | --- | --- | --- |
138-
| `name` | Name of the app to be accessed | `apps[0].name=grafana` | | Yes |
139-
| `uri` | URI of the app to be accessed | `apps[0].uri=http://localhost:3000` | | Yes |
140-
| `public_addr` | Public address used to access the app | `apps[0].public_addr=grafana.teleport.example.com` | | No |
141-
| `labels.[name]` | Key-value pairs to set against the app for grouping/RBAC | `apps[0].labels.env=local,apps[0].labels.region=us-west-1` | | No |
142-
| `insecure_skip_verify` | Whether to skip validation of TLS certificates presented by backend apps | `apps[0].insecure_skip_verify=true` | `false` | No |
143-
| `rewrite.redirect` | A list of URLs to rewrite to the public address of the app service | `apps[0].rewrite.redirect[0]=https://192.168.1.1` | | No
137+
| Key | Description | Example | Default | Required |
138+
| ---------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------- | ------- | -------- |
139+
| `name` | Name of the app to be accessed | `apps[0].name=grafana` | | Yes |
140+
| `uri` | URI of the app to be accessed | `apps[0].uri=http://localhost:3000` | | Yes |
141+
| `public_addr` | Public address used to access the app | `apps[0].public_addr=grafana.teleport.example.com` | | No |
142+
| `labels.[name]` | Key-value pairs to set against the app for grouping/RBAC | `apps[0].labels.env=local,apps[0].labels.region=us-west-1` | | No |
143+
| `insecure_skip_verify` | Whether to skip validation of TLS certificates presented by backend apps | `apps[0].insecure_skip_verify=true` | `false` | No |
144+
| `rewrite.redirect` | A list of URLs to rewrite to the public address of the app service | `apps[0].rewrite.redirect[0]=https://192.168.1.1` | | No |
144145

145146
You can add multiple apps using `apps[1].name`, `apps[1].uri`, `apps[2].name`, `apps[2].uri` etc.
146147

@@ -219,14 +220,14 @@ Set the values in the above command as appropriate for your setup.
219220

220221
These are the supported values for the `databases` map:
221222

222-
| Key | Description | Example | Default | Required |
223-
| --- | --- | --- | --- | --- |
224-
| `name` | Name of the database to be accessed | `databases[0].name=aurora` | | Yes |
225-
| `uri` | URI of the database to be accessed | `databases[0].uri=postgres-aurora-instance-1.xxx.us-east-1.rds.amazonaws.com:5432` | | Yes |
226-
| `protocol` | Database protocol | `databases[0].protocol=postgres` | | Yes |
227-
| `description` | Free-form description of the database proxy instance | `databases[0].description='AWS Aurora instance of PostgreSQL 13.0'` | | No |
228-
| `aws.region` | AWS-specific region configuration (only used for RDS/Aurora) | `databases[0].aws.region=us-east-1` | | No |
229-
| `labels.[name]` | Key-value pairs to set against the database for grouping/RBAC | `databases[0].labels.db=postgres-dev,apps[0].labels.region=us-east-1` | | No |
223+
| Key | Description | Example | Default | Required |
224+
| --------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------- | -------- |
225+
| `name` | Name of the database to be accessed | `databases[0].name=aurora` | | Yes |
226+
| `uri` | URI of the database to be accessed | `databases[0].uri=postgres-aurora-instance-1.xxx.us-east-1.rds.amazonaws.com:5432` | | Yes |
227+
| `protocol` | Database protocol | `databases[0].protocol=postgres` | | Yes |
228+
| `description` | Free-form description of the database proxy instance | `databases[0].description='AWS Aurora instance of PostgreSQL 13.0'` | | No |
229+
| `aws.region` | AWS-specific region configuration (only used for RDS/Aurora) | `databases[0].aws.region=us-east-1` | | No |
230+
| `labels.[name]` | Key-value pairs to set against the database for grouping/RBAC | `databases[0].labels.db=postgres-dev,apps[0].labels.region=us-east-1` | | No |
230231

231232
You can add multiple databases using `databases[1].name`, `databases[1].uri`, `databases[1].protocol`,
232233
`databases[2].name`, `databases[2].uri`, `databases[2].protocol` etc.
@@ -255,6 +256,62 @@ to use for discovery you can use `kubernetesDiscovery` property of the chart.
255256
When discovery is running, `kubeClusterName` should be set in values, since it is used as a name for discovery field and as a target label
256257
for the app service, so it can expose discovered apps.
257258

259+
## Jamf service
260+
261+
To use [Teleport Jamf service](https://goteleport.com/docs/access-controls/device-trust/jamf-integration/),
262+
you will also need:
263+
- provide your Jamf Pro API endpoint
264+
- provide your Jamf Pro API credentials
265+
266+
To install the agent with Jamf API credentials, run:
267+
268+
```sh
269+
$ helm install teleport-kube-agent . \
270+
--create-namespace \
271+
--namespace teleport \
272+
--set roles=jamf \
273+
--set proxyAddr=${PROXY_ENDPOINT?} \
274+
--set authToken=${JOIN_TOKEN?} \
275+
--set jamfApiEndpoint=${JAMF_API_ENDPOINT?} \
276+
--set jamfClientId=${JAMF_CLIENT_ID?} \
277+
--set jamfClientSecret=${JAMF_CLIENT_SECRET?}
278+
```
279+
280+
Set the values in the above command as appropriate for your setup.
281+
282+
The Helm chart will install Secrets by default. To avoid specifying the Jamf API credentials in plain text, it's possible to create a secret containing the password beforehand. To do so, run:
283+
284+
```sh
285+
export JAMF_CLIENT_SECRET=`<jamf client secret> | base64 -w0`
286+
export JAMF_SECRET_NAME=teleport-jamf-api-credentials
287+
export TELEPORT_NAMESPACE=teleport
288+
289+
cat <<EOF > secrets.yaml
290+
---
291+
apiVersion: v1
292+
kind: Secret
293+
metadata:
294+
name: ${JAMF_SECRET_NAME}
295+
namespace: ${TELEPORT_NAMESPACE?}
296+
type: Opaque
297+
data:
298+
jamfSecret: ${JAMF_CLIENT_SECRET?}
299+
EOF
300+
301+
$ kubectl apply -f secret.yaml
302+
303+
$ helm install teleport-kube-agent . \
304+
--create-namespace \
305+
--namespace ${TELEPORT_NAMESPACE?} \
306+
--set roles=jamf \
307+
--set proxyAddr=${PROXY_ENDPOINT?} \
308+
--set authToken=${JOIN_TOKEN?} \
309+
--set jamfApiEndpoint=${JAMF_API_ENDPOINT?} \
310+
--set jamfClientId=${JAMF_CLIENT_ID?} \
311+
--set jamfCredentialsSecret.name=${JAMF_SECRET_NAME?} \
312+
--set jamfCredentialsSecret.create=false
313+
```
314+
258315
## Troubleshooting
259316

260317
If the service for a given role doesn't show up, look into the agent logs with:

examples/chart/teleport-kube-agent/templates/_config.tpl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ discovery_service:
128128
enabled: false
129129
{{- end }}
130130

131+
jamf_service:
132+
{{- if contains "jamf" (.Values.roles | toString) }}
133+
enabled: true
134+
api_endpoint: {{ required "jamfApiEndpoint is required in chart values when jamf role is enabled, see README" .Values.jamfApiEndpoint }}
135+
client_id: {{ required "jamfClientId is required in chart values when jamf role is enabled, see README" .Values.jamfClientId }}
136+
client_secret_file: "/etc/teleport-jamf-api-credentials/credential"
137+
{{- else }}
138+
enabled: false
139+
{{- end }}
140+
131141
auth_service:
132142
enabled: false
133143
ssh_service:

examples/chart/teleport-kube-agent/templates/deployment.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ spec:
111111
name: "teleport-tls-ca"
112112
readOnly: true
113113
{{- end }}
114+
{{- if contains "jamf" (.Values.roles | toString) }}
115+
- mountPath: /etc/teleport-jamf-api-credentials
116+
name: "jamf-api-credentials"
117+
readOnly: true
118+
{{- end }}
114119
{{- if .Values.extraVolumeMounts }}
115120
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
116121
{{- end }}
@@ -192,6 +197,11 @@ spec:
192197
name: "teleport-tls-ca"
193198
readOnly: true
194199
{{- end }}
200+
{{- if contains "jamf" (.Values.roles | toString) }}
201+
- mountPath: /etc/teleport-jamf-api-credentials
202+
name: "jamf-api-credentials"
203+
readOnly: true
204+
{{- end }}
195205
{{- if .Values.extraVolumeMounts }}
196206
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
197207
{{- end }}
@@ -214,6 +224,11 @@ spec:
214224
secret:
215225
secretName: {{ .Values.tls.existingCASecretName }}
216226
{{- end }}
227+
{{- if contains "jamf" (.Values.roles | toString) }}
228+
- name: "jamf-api-credentials"
229+
secret:
230+
secretName: {{ .Values.jamfCredentialsSecret.name }}
231+
{{- end }}
217232
{{- if .Values.extraVolumes }}
218233
{{- toYaml .Values.extraVolumes | nindent 6 }}
219234
{{- end }}

examples/chart/teleport-kube-agent/templates/secret.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,23 @@ stringData:
1717
auth-token: |
1818
{{ coalesce .Values.joinParams.tokenName .Values.authToken }}
1919
{{- end}}
20+
21+
{{- if and (contains "jamf" (.Values.roles | toString)) .Values.jamfCredentialsSecret.create }}
22+
---
23+
apiVersion: v1
24+
kind: Secret
25+
metadata:
26+
name: {{ .Values.jamfCredentialsSecret.name }}
27+
namespace: {{ .Release.Namespace }}
28+
{{- if .Values.extraLabels.secret }}
29+
labels:
30+
{{- toYaml .Values.extraLabels.secret | nindent 4 }}
31+
{{- end }}
32+
{{- if .Values.annotations.secret }}
33+
annotations:
34+
{{- toYaml .Values.annotations.secret | nindent 4 }}
35+
{{- end }}
36+
type: Opaque
37+
stringData:
38+
credential: {{ required "jamfClientSecret is required in chart values when jamf role is enabled, see README" .Values.jamfClientSecret }}
39+
{{- end}}

examples/chart/teleport-kube-agent/templates/statefulset.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ spec:
107107
name: "teleport-tls-ca"
108108
readOnly: true
109109
{{- end }}
110+
{{- if contains "jamf" (.Values.roles | toString) }}
111+
- mountPath: /etc/teleport-jamf-api-credentials
112+
name: "jamf-api-credentials"
113+
readOnly: true
114+
{{- end }}
110115
{{- if .Values.extraVolumeMounts }}
111116
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
112117
{{- end }}
@@ -207,6 +212,11 @@ spec:
207212
name: "teleport-tls-ca"
208213
readOnly: true
209214
{{- end }}
215+
{{- if contains "jamf" (.Values.roles | toString) }}
216+
- mountPath: /etc/teleport-jamf-api-credentials
217+
name: "jamf-api-credentials"
218+
readOnly: true
219+
{{- end }}
210220
{{- if .Values.extraVolumeMounts }}
211221
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
212222
{{- end }}
@@ -229,6 +239,11 @@ spec:
229239
secret:
230240
secretName: {{ .Values.tls.existingCASecretName }}
231241
{{- end }}
242+
{{- if contains "jamf" (.Values.roles | toString) }}
243+
- name: "jamf-api-credentials"
244+
secret:
245+
secretName: {{ .Values.jamfCredentialsSecret.name }}
246+
{{- end }}
232247
{{- if .Values.extraVolumes }}
233248
{{- toYaml .Values.extraVolumes | nindent 6 }}
234249
{{- end }}

0 commit comments

Comments
 (0)