Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

helm: Add support for jamf_service to the teleport-kube-agent Helm chart #42368

Merged
merged 22 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@
"ioreg",
"isnt",
"isrgrootx",
"jamfapiendpoint",
"jamfclientid",
"javapipeline",
"jetbrains",
"jiraapitoken",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ when running the `teleport-kube-agent` chart.
| Teleport Application service | `app` | [`apps`](#apps) or [`appResources`](#appresources) |
| Teleport Database service | `db` | [`databases`](#databases) or [`databaseResources`](#databaseresources) |
| Teleport Discovery service | `discovery` | [`kubeClusterName`](#kubeclustername) |
| Teleport Jamf service | `jamf` | [`jamfApiEndpoint`](#jamfapiendpoint), [`jamfClientId`](#jamfclientid) |

For example:
```yaml
Expand Down Expand Up @@ -454,6 +455,114 @@ kubernetesDiscovery:
env: testing
```

## `jamfApiEndpoint`

| Type | Default |
|------|---------|
| `string` | `""` |

`jamfApiEndpoint` sets the Jamf Pro API endpoint used for Jamf service.
Example: "https://yourtenant.jamfcloud.com/api".

This setting is required if the chart `roles` contains `jamf`.

## `jamfClientId`

| Type | Default |
|------|---------|
| `string` | `""` |

`jamfClientId` sets the Jamf Pro API Client ID used for Jamf service.

This setting is required if the chart `roles` contains `jamf`.

## `jamfClientSecret`

| Type | Default |
|------|---------|
| `string` | `""` |

`jamfClientSecret` sets the Jamf Pro API password used for Jamf service.

This setting is required if the chart `roles` contains `jamf`.

## `jamfUsername`

| Type | Default |
|------|---------|
| `string` | `""` |

`jamfUsername` sets the Jamf Pro API username used for Jamf service.

This setting is required if the chart `roles` contains `jamf`.

## `jamfPassword`

| Type | Default |
|------|---------|
| `string` | `""` |

`jamfPassword` sets the Jamf Pro API password used for Jamf service.

This setting is required if the chart `roles` contains `jamf`.

## `jamfCredentialsSecret`

`jamfCredentialsSecret` manages the Jamf Pro API secret creation and its name.

### `jamfCredentialsSecret.create`

| Type | Default |
|------|---------|
| `bool` | `true` |

`jamfCredentialsSecret.create` controls whether the chart creates the
Kubernetes `Secret` containing the Jamf Pro API Client Secret.
If false, you must create a Kubernetes Secret with the configured name in
the Helm release namespace.

### `jamfCredentialsSecret.name`

| Type | Default |
|------|---------|
| `string` | `"teleport-jamf-api-credentials"` |

`jamfCredentialsSecret.name` is the name of the Kubernetes Secret
containing the Jamf Pro API Client Secret used by the chart.

If `jamfCredentialsSecret.create` is `false`, the chart will not attempt to create the secret itself.
Instead, it will read the value from an existing secret. `jamfCredentialsSecret.name`
configures the name of this secret. This allows you to configure this secret externally and avoid having a plaintext
Jamf Pro API Client Secret stored in your Teleport chart values.

To create your own Jamf Pro API Client Secret, you can use a command like this:

```code
$ kubectl --namespace teleport create secret generic my-jamf-secret --from-literal=jamfSecret=<replace-with-actual-secret>
```

<Admonition type="note">
The key used for the Jamf Pro API Client Secret inside the secret must be `jamfSecret`, as in the command above.
</Admonition>

For example:

```yaml
jamfCredentialsSecret:
create: false
name: my-jamf-secret
```

For Teleport versions lower than v16, use Jamf Pro API password:

```code
$ kubectl --namespace teleport create secret generic my-jamf-secret --from-literal=jamfSecret=<replace-with-actual-password>
```

<Admonition type="note">
The key used for the Jamf Pro API password inside the secret must be `jamfSecret`, as in the command above.
</Admonition>

## `teleportVersionOverride`

| Type | Default |
Expand Down
52 changes: 27 additions & 25 deletions docs/pages/reference/helm-reference/teleport-kube-agent.mdx

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion examples/chart/teleport-kube-agent/.lint/all-v6.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
authToken: auth-token
proxyAddr: proxy.example.com:3080
roles: kube,app,db
roles: kube,app,db,jamf
kubeClusterName: test-kube-cluster-name
labels:
cluster: testing
Expand All @@ -15,6 +15,9 @@ databases:
protocol: "postgres"
labels:
database: staging
jamfApiEndpoint: "testjamf.jamfcloud.com/api"
jamfClientId: teleport-jamf-client-id
jamfClientSecret: secret-jamf-client-secret
annotations:
config:
kubernetes.io/config: "test-annotation"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
authToken: auth-token
proxyAddr: proxy.example.com:3080
roles: jamf
jamfApiEndpoint: "https://testjamf.jamfcloud.com/api"
jamfUsername: teleport-jamf
jamfCredentialsSecret:
create: false
name: existing-teleport-jamf-secret
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
authToken: auth-token
proxyAddr: proxy.example.com:3080
roles: jamf
jamfApiEndpoint: "https://testjamf.jamfcloud.com/api"
jamfClientId: teleport-jamf-client-id
jamfCredentialsSecret:
create: false
name: existing-teleport-jamf-secret
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
authToken: auth-token
proxyAddr: proxy.example.com:3080
roles: jamf
jamfApiEndpoint: "https://testjamf.jamfcloud.com/api"
jamfUsername: teleport-jamf
jamfPassword: secret-jamf-password
6 changes: 6 additions & 0 deletions examples/chart/teleport-kube-agent/.lint/jamf-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
authToken: auth-token
proxyAddr: proxy.example.com:3080
roles: jamf
jamfApiEndpoint: "https://testjamf.jamfcloud.com/api"
jamfClientId: teleport-jamf-client-id
jamfClientSecret: secret-jamf-client-secret
102 changes: 86 additions & 16 deletions examples/chart/teleport-kube-agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ with an existing Teleport cluster:
- Teleport Application access
- Teleport Database access
- Teleport Kubernetes App Discovery
- Teleport Jamf service

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

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

| Key | Description | Example | Default | Required |
| --- | --- | --- | --- | --- |
| `name` | Name of the app to be accessed | `apps[0].name=grafana` | | Yes |
| `uri` | URI of the app to be accessed | `apps[0].uri=http://localhost:3000` | | Yes |
| `public_addr` | Public address used to access the app | `apps[0].public_addr=grafana.teleport.example.com` | | No |
| `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 |
| `insecure_skip_verify` | Whether to skip validation of TLS certificates presented by backend apps | `apps[0].insecure_skip_verify=true` | `false` | No |
| `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
| Key | Description | Example | Default | Required |
| ---------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------- | ------- | -------- |
| `name` | Name of the app to be accessed | `apps[0].name=grafana` | | Yes |
| `uri` | URI of the app to be accessed | `apps[0].uri=http://localhost:3000` | | Yes |
| `public_addr` | Public address used to access the app | `apps[0].public_addr=grafana.teleport.example.com` | | No |
| `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 |
| `insecure_skip_verify` | Whether to skip validation of TLS certificates presented by backend apps | `apps[0].insecure_skip_verify=true` | `false` | No |
| `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 |

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

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

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

| Key | Description | Example | Default | Required |
| --- | --- | --- | --- | --- |
| `name` | Name of the database to be accessed | `databases[0].name=aurora` | | Yes |
| `uri` | URI of the database to be accessed | `databases[0].uri=postgres-aurora-instance-1.xxx.us-east-1.rds.amazonaws.com:5432` | | Yes |
| `protocol` | Database protocol | `databases[0].protocol=postgres` | | Yes |
| `description` | Free-form description of the database proxy instance | `databases[0].description='AWS Aurora instance of PostgreSQL 13.0'` | | No |
| `aws.region` | AWS-specific region configuration (only used for RDS/Aurora) | `databases[0].aws.region=us-east-1` | | No |
| `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 |
| Key | Description | Example | Default | Required |
| --------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------- | -------- |
| `name` | Name of the database to be accessed | `databases[0].name=aurora` | | Yes |
| `uri` | URI of the database to be accessed | `databases[0].uri=postgres-aurora-instance-1.xxx.us-east-1.rds.amazonaws.com:5432` | | Yes |
| `protocol` | Database protocol | `databases[0].protocol=postgres` | | Yes |
| `description` | Free-form description of the database proxy instance | `databases[0].description='AWS Aurora instance of PostgreSQL 13.0'` | | No |
| `aws.region` | AWS-specific region configuration (only used for RDS/Aurora) | `databases[0].aws.region=us-east-1` | | No |
| `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 |

You can add multiple databases using `databases[1].name`, `databases[1].uri`, `databases[1].protocol`,
`databases[2].name`, `databases[2].uri`, `databases[2].protocol` etc.
Expand Down Expand Up @@ -255,6 +256,75 @@ to use for discovery you can use `kubernetesDiscovery` property of the chart.
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
for the app service, so it can expose discovered apps.

## Jamf service

To use [Teleport Jamf service](https://goteleport.com/docs/access-controls/device-trust/jamf-integration/),
you will also need:
- provide your Jamf Pro API endpoint
- provide your Jamf Pro API credentials
- Teleport versions v16.0.0 or lower don't support Jamf API credentials. Use [Jamf user and password authentication](https://goteleport.com/docs/ver/16.x/access-controls/device-trust/jamf-integration/#optional-using-jamf-user-and-password-authentication) instead.
- Teleport versions higher than v16.0.0 should use [Jamf API credentials](https://learn.jamf.com/en-US/bundle/jamf-pro-documentation-current/page/API_Roles_and_Clients.html).

To install the agent with Jamf API credentials, run:

```sh
$ helm install teleport-kube-agent . \
--create-namespace \
--namespace teleport \
--set roles=jamf \
--set proxyAddr=${PROXY_ENDPOINT?} \
--set jamfApiEndpoint=${JAMF_API_ENDPOINT?} \
--set jamfClientId=${JAMF_CLIENT_ID?} \
--set jamfClientSecret=${JAMF_CLIENT_SECRET?}
```

For Jamf username and password, run:

```sh
$ helm install teleport-kube-agent . \
--create-namespace \
--namespace teleport \
--set roles=jamf \
--set proxyAddr=${PROXY_ENDPOINT?} \
--set jamfApiEndpoint=${JAMF_API_ENDPOINT?} \
--set jamfUsername=${JAMF_USERNAME?} \
--set jamfPassword=${JAMF_PASSWORD?}
```

Set the values in the above command as appropriate for your setup.

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:

```sh
export JAMF_CLIENT_SECRET=`<jamf client secret> | base64 -w0`
export JAMF_SECRET_NAME=teleport-jamf-api-credentials
export TELEPORT_NAMESPACE=teleport

cat <<EOF > secrets.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: ${JAMF_SECRET_NAME}
namespace: ${TELEPORT_NAMESPACE?}
type: Opaque
data:
jamfSecret: ${JAMF_CLIENT_SECRET?}
EOF

$ kubectl apply -f secret.yaml

$ helm install teleport-kube-agent . \
--create-namespace \
--namespace ${TELEPORT_NAMESPACE?} \
--set roles=jamf \
--set proxyAddr=${PROXY_ENDPOINT?} \
--set jamfApiEndpoint=${JAMF_API_ENDPOINT?} \
--set jamfClientId=${JAMF_CLIENT_ID?} \
--set jamfCredentialsSecret.name=${JAMF_SECRET_NAME?} \
--set jamfCredentialsSecret.create=false
```

## Troubleshooting

If the service for a given role doesn't show up, look into the agent logs with:
Expand Down
15 changes: 15 additions & 0 deletions examples/chart/teleport-kube-agent/templates/_config.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,21 @@ discovery_service:
enabled: false
{{- end }}

jamf_service:
{{- if contains "jamf" (.Values.roles | toString) }}
enabled: true
api_endpoint: {{ required "jamfApiEndpoint is required in chart values when jamf role is enabled, see README" .Values.jamfApiEndpoint }}
{{- if .Values.jamfUsername }}
lcharkiewicz marked this conversation as resolved.
Show resolved Hide resolved
username: {{ required "jamfUsername is required in chart values when jamf role is enabled, see README" .Values.jamfUsername }}
lcharkiewicz marked this conversation as resolved.
Show resolved Hide resolved
password_file: "/etc/teleport-jamf-api-credentials/secret"
{{- else }}
client_id: {{ required "jamfClientId is required in chart values when jamf role is enabled, see README" .Values.jamfClientId }}
client_secret_file: "/etc/teleport-jamf-api-credentials/secret"
{{- end }}
{{- else }}
enabled: false
{{- end }}

auth_service:
enabled: false
ssh_service:
Expand Down
18 changes: 18 additions & 0 deletions examples/chart/teleport-kube-agent/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ spec:
name: "teleport-tls-ca"
readOnly: true
{{- end }}
{{- if contains "jamf" (.Values.roles | toString) }}
- mountPath: /etc/teleport-jamf-api-credentials
name: "jamf-api-credentials"
readOnly: true
{{- end }}
{{- if .Values.extraVolumeMounts }}
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
{{- end }}
Expand Down Expand Up @@ -192,6 +197,11 @@ spec:
name: "teleport-tls-ca"
readOnly: true
{{- end }}
{{- if contains "jamf" (.Values.roles | toString) }}
- mountPath: /etc/teleport-jamf-api-credentials
name: "jamf-api-credentials"
readOnly: true
{{- end }}
{{- if .Values.extraVolumeMounts }}
{{- toYaml .Values.extraVolumeMounts | nindent 8 }}
{{- end }}
Expand All @@ -214,6 +224,14 @@ spec:
secret:
secretName: {{ .Values.tls.existingCASecretName }}
{{- end }}
{{- if contains "jamf" (.Values.roles | toString) }}
- name: "jamf-api-credentials"
secret:
secretName: {{ .Values.jamfCredentialsSecret.name }}
items:
- key: jamfSecret
path: secret
lcharkiewicz marked this conversation as resolved.
Show resolved Hide resolved
{{- end }}
{{- if .Values.extraVolumes }}
{{- toYaml .Values.extraVolumes | nindent 6 }}
{{- end }}
Expand Down
Loading
Loading