diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b05e2ae0..c5d1702f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,7 +37,7 @@ jobs: go-version: ${{ steps.go-version.outputs.result }} - id: release - run: make release ark-release + run: make release ark-release ngts-release outputs: RELEASE_OCI_PREFLIGHT_IMAGE: ${{ steps.release.outputs.RELEASE_OCI_PREFLIGHT_IMAGE }} @@ -50,6 +50,12 @@ jobs: ARK_CHART: ${{ steps.release.outputs.ARK_CHART }} ARK_CHART_TAG: ${{ steps.release.outputs.ARK_CHART_TAG }} ARK_CHART_DIGEST: ${{ steps.release.outputs.ARK_CHART_DIGEST }} + NGTS_IMAGE: ${{ steps.release.outputs.NGTS_IMAGE }} + NGTS_IMAGE_TAG: ${{ steps.release.outputs.NGTS_IMAGE_TAG }} + NGTS_IMAGE_DIGEST: ${{ steps.release.outputs.NGTS_IMAGE_DIGEST }} + NGTS_CHART: ${{ steps.release.outputs.NGTS_CHART }} + NGTS_CHART_TAG: ${{ steps.release.outputs.NGTS_CHART_TAG }} + NGTS_CHART_DIGEST: ${{ steps.release.outputs.NGTS_CHART_DIGEST }} github_release: runs-on: ubuntu-latest @@ -73,6 +79,12 @@ jobs: echo "ARK_CHART: ${{ needs.build_and_push.outputs.ARK_CHART }}" >> .notes-file echo "ARK_CHART_TAG: ${{ needs.build_and_push.outputs.ARK_CHART_TAG }}" >> .notes-file echo "ARK_CHART_DIGEST: ${{ needs.build_and_push.outputs.ARK_CHART_DIGEST }}" >> .notes-file + echo "NGTS_IMAGE: ${{ needs.build_and_push.outputs.NGTS_IMAGE }}" >> .notes-file + echo "NGTS_IMAGE_TAG: ${{ needs.build_and_push.outputs.NGTS_IMAGE_TAG }}" >> .notes-file + echo "NGTS_IMAGE_DIGEST: ${{ needs.build_and_push.outputs.NGTS_IMAGE_DIGEST }}" >> .notes-file + echo "NGTS_CHART: ${{ needs.build_and_push.outputs.NGTS_CHART }}" >> .notes-file + echo "NGTS_CHART_TAG: ${{ needs.build_and_push.outputs.NGTS_CHART_TAG }}" >> .notes-file + echo "NGTS_CHART_DIGEST: ${{ needs.build_and_push.outputs.NGTS_CHART_DIGEST }}" >> .notes-file - env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index e701c330..c969c176 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -109,6 +109,41 @@ jobs: ARK_USERNAME: ${{ secrets.ARK_USERNAME }} ARK_SECRET: ${{ secrets.ARK_SECRET }} + ngts-test-e2e: + # TEMPORARY: require an explicit label to test NGTS until we have a stable test environment + if: contains(github.event.pull_request.labels.*.name, 'test-ngts') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + # Adding `fetch-depth: 0` makes sure tags are also fetched. We need + # the tags so `git describe` returns a valid version. + # see https://github.com/actions/checkout/issues/701 for extra info about this option + with: { fetch-depth: 0 } + + - uses: ./.github/actions/repo_access + with: + DEPLOY_KEY_READ_VENAFI_CONNECTION_LIB: ${{ secrets.DEPLOY_KEY_READ_VENAFI_CONNECTION_LIB }} + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: _bin/downloaded + key: downloaded-${{ runner.os }}-${{ hashFiles('klone.yaml') }}-test-unit + + - run: make -j ngts-test-e2e + env: + OCI_BASE: ${{ secrets.NGTS_OCI_BASE }} + NGTS_CLIENT_ID: ${{ secrets.NGTS_CLIENT_ID }} + NGTS_PRIVATE_KEY: ${{ secrets.NGTS_PRIVATE_KEY }} + NGTS_TSG_ID: ${{ secrets.NGTS_TSG_ID }} + test-e2e: if: contains(github.event.pull_request.labels.*.name, 'test-e2e') runs-on: ubuntu-latest @@ -149,7 +184,7 @@ jobs: id: timestamp # Give the step an ID to reference its output run: | # Generate a timestamp in the format YYMMDD-HHMMSS. - # Extracting from PR name would require sanitization due to GKE cluster naming constraints + # Extracting from PR name would require sanitization due to GKE cluster naming constraints TIMESTAMP=$(date +'%y%m%d-%H%M%S') CLUSTER_NAME="test-secretless-${TIMESTAMP}" echo "Generated cluster name: ${CLUSTER_NAME}" diff --git a/deploy/charts/disco-agent/templates/_helpers.tpl b/deploy/charts/disco-agent/templates/_helpers.tpl index ad6dadc9..b38cb1b8 100644 --- a/deploy/charts/disco-agent/templates/_helpers.tpl +++ b/deploy/charts/disco-agent/templates/_helpers.tpl @@ -62,10 +62,8 @@ Create the name of the service account to use {{- end }} {{/* -Util function for generating the image URL based on the provided options. -IMPORTANT: This function is standardized across all charts in the cert-manager GH organization. -Any changes to this function should also be made in cert-manager, trust-manager, approver-policy, ... -See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linked PRs. +Util function for generating an image reference based on the provided options. +This function is derived from similar functions used in the cert-manager GitHub organization */}} {{- define "image" -}} {{- /* diff --git a/deploy/charts/discovery-agent/README.md b/deploy/charts/discovery-agent/README.md index 3f3330f5..378c5397 100644 --- a/deploy/charts/discovery-agent/README.md +++ b/deploy/charts/discovery-agent/README.md @@ -6,6 +6,79 @@ The Discovery Agent connects your Kubernetes or OpenShift cluster to Palo Alto N +#### **config.tsgID** ~ `string,number` +> Default value: +> ```yaml +> "" +> ``` + +Required: The TSG (Tenant Service Group) ID to use when connecting to SCM. NB: TSG IDs are numeric, but should be treated as strings. If being set with the Helm CLI prefer `--set-string`. + + +#### **config.clusterName** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Required: A human readable name for the cluster into which the agent is being deployed. + +This cluster name will be associated with the data that the agent uploads to the backend. + +#### **config.clusterDescription** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +A short description of the cluster where the agent is deployed (optional). + +This description will be associated with the data that the agent uploads to the backend. + +#### **config.period** ~ `string` +> Default value: +> ```yaml +> 0h1m0s +> ``` + +How often to push data to the remote server + +#### **config.excludeAnnotationKeysRegex** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +You can configure the agent to exclude some annotations or labels from being pushed. All Kubernetes objects are affected. The objects are still pushed, but the specified annotations and labels are removed before being pushed. + +Dots is the only character that needs to be escaped in the regex. Use either double quotes with escaped single quotes or unquoted strings for the regex to avoid YAML parsing issues with `\.`. + +Example: excludeAnnotationKeysRegex: ['^kapp\.k14s\.io/original.*'] +#### **config.excludeLabelKeysRegex** ~ `array` +> Default value: +> ```yaml +> [] +> ``` +#### **config.clientID** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Deprecated: Client ID for the configured service account. The client ID should be provided in the "clientID" field of the authentication secret (see config.secretName). This field is provided for compatibility for users migrating from the "venafi-kubernetes-agent" chart. + +#### **config.secretName** ~ `string` +> Default value: +> ```yaml +> discovery-agent-credentials +> ``` + +The name of the Secret containing the NGTS built-in service account credentials. +The Secret must contain the following key: +- privatekey.pem: PEM-encoded private key for the service account +The Secret should also contain the following key: +- clientID: Service account client ID (config.clientID must be set if not present) + #### **replicaCount** ~ `number` > Default value: > ```yaml @@ -32,17 +105,6 @@ Examples: - jetstack - custom-namespace -#### **image.registry** ~ `string` - -Deprecated: per-component registry prefix. - -If set, this value is *prepended* to the image repository that the chart would otherwise render. This applies both when `image.repository` is set and when the repository is computed from -`imageRegistry` + `imageNamespace` + `image.name`. - -This can produce "double registry" style references such as -`legacy.example.io/quay.io/jetstack/...`. Prefer using the global -`imageRegistry`/`imageNamespace` values. - #### **image.repository** ~ `string` > Default value: > ```yaml @@ -219,76 +281,6 @@ Configures the NO_PROXY environment variable where a HTTP proxy is required, but Configure a PodDisruptionBudget for the agent's Deployment. If running with multiple replicas, consider setting podDisruptionBudget.enabled to true. -#### **config.period** ~ `string` -> Default value: -> ```yaml -> 0h1m0s -> ``` - -Push data every 12 hours unless changed. -#### **config.excludeAnnotationKeysRegex** ~ `array` -> Default value: -> ```yaml -> [] -> ``` - -You can configure the agent to exclude some annotations or labels from being pushed. All Kubernetes objects are affected. The objects are still pushed, but the specified annotations and labels are removed before being pushed. - -Dots is the only character that needs to be escaped in the regex. Use either double quotes with escaped single quotes or unquoted strings for the regex to avoid YAML parsing issues with `\.`. - -Example: excludeAnnotationKeysRegex: ['^kapp\.k14s\.io/original.*'] -#### **config.excludeLabelKeysRegex** ~ `array` -> Default value: -> ```yaml -> [] -> ``` -#### **config.clusterName** ~ `string` -> Default value: -> ```yaml -> "" -> ``` - -A human readable name for the cluster where the agent is deployed (required). - -This cluster name will be associated with the data that the agent uploads to the NGTS service. -#### **config.clusterDescription** ~ `string` -> Default value: -> ```yaml -> "" -> ``` - -A short description of the cluster where the agent is deployed (optional). - -This description will be associated with the data that the agent uploads to the NGTS service. The description may include contact information such as the email address of the cluster administrator. -#### **config.clientID** ~ `string` -> Default value: -> ```yaml -> "" -> ``` - -Deprecated: Client ID for the configured service account. The client ID should be provided in the "clientID" field of the authentication secret (see config.secretName). - -#### **config.tsgID** ~ `string` -> Default value: -> ```yaml -> "" -> ``` - -The TSG (Tenant Security Group) ID for your NGTS account (required). NB: TSG IDs are numeric, but must be provided as strings (in double quotes). - - -#### **config.secretName** ~ `string` -> Default value: -> ```yaml -> discovery-agent-credentials -> ``` - -The name of the Secret containing the NGTS service account credentials. -The Secret must contain the following key: -- privatekey.pem: PEM-encoded private key for the service account -The Secret may contain the following key: -- clientID: Service account client ID (config.clientID must be set if not present) - #### **extraArgs** ~ `array` > Default value: > ```yaml diff --git a/deploy/charts/discovery-agent/templates/_helpers.tpl b/deploy/charts/discovery-agent/templates/_helpers.tpl index 9ee2ecf3..ad972b80 100644 --- a/deploy/charts/discovery-agent/templates/_helpers.tpl +++ b/deploy/charts/discovery-agent/templates/_helpers.tpl @@ -62,10 +62,8 @@ Create the name of the service account to use {{- end }} {{/* -Util function for generating the image URL based on the provided options. -IMPORTANT: This function is standardized across all charts in the cert-manager GH organization. -Any changes to this function should also be made in cert-manager, trust-manager, approver-policy, ... -See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linked PRs. +Util function for generating an image reference based on the provided options. +This function is derived from similar functions used in the cert-manager GitHub organization */}} {{- define "image" -}} {{- /* @@ -85,12 +83,6 @@ usage through tuple/variable indirection. {{- $repository := "" -}} {{- if $image.repository -}} {{- $repository = $image.repository -}} - {{- /* - Backwards compatibility: if image.registry is set, additionally prefix the repository with this registry. - */ -}} - {{- if $image.registry -}} - {{- $repository = printf "%s/%s" $image.registry $repository -}} - {{- end -}} {{- else -}} {{- $name := required "ERROR: image.name must be set when image.repository is empty" $image.name -}} {{- $repository = $name -}} @@ -100,12 +92,6 @@ usage through tuple/variable indirection. {{- if $imageRegistry -}} {{- $repository = printf "%s/%s" $imageRegistry $repository -}} {{- end -}} - {{- /* - Backwards compatibility: if image.registry is set, additionally prefix the repository with this registry. - */ -}} - {{- if $image.registry -}} - {{- $repository = printf "%s/%s" $image.registry $repository -}} - {{- end -}} {{- end -}} {{- $repository -}} {{- if and $image.tag $image.digest -}} diff --git a/deploy/charts/discovery-agent/templates/configmap.yaml b/deploy/charts/discovery-agent/templates/configmap.yaml index 65c0a9ce..63677cc3 100644 --- a/deploy/charts/discovery-agent/templates/configmap.yaml +++ b/deploy/charts/discovery-agent/templates/configmap.yaml @@ -20,9 +20,9 @@ data: {{- end }} data-gatherers: - kind: k8s-discovery - name: ngts/discovery + name: k8s/discovery - kind: k8s-dynamic - name: ngts/secrets + name: k8s/secrets config: resource-type: version: v1 @@ -33,42 +33,42 @@ data: - type!=bootstrap.kubernetes.io/token - type!=helm.sh/release.v1 - kind: k8s-dynamic - name: ngts/jobs + name: k8s/jobs config: resource-type: version: v1 group: batch resource: jobs - kind: k8s-dynamic - name: ngts/cronjobs + name: k8s/cronjobs config: resource-type: version: v1 group: batch resource: cronjobs - kind: k8s-dynamic - name: ngts/deployments + name: k8s/deployments config: resource-type: version: v1 group: apps resource: deployments - kind: k8s-dynamic - name: ngts/statefulsets + name: k8s/statefulsets config: resource-type: version: v1 group: apps resource: statefulsets - kind: k8s-dynamic - name: ngts/daemonsets + name: k8s/daemonsets config: resource-type: version: v1 group: apps resource: daemonsets - kind: k8s-dynamic - name: ngts/pods + name: k8s/pods config: resource-type: version: v1 diff --git a/deploy/charts/discovery-agent/templates/rbac.yaml b/deploy/charts/discovery-agent/templates/rbac.yaml index 6d9d204d..91609b85 100644 --- a/deploy/charts/discovery-agent/templates/rbac.yaml +++ b/deploy/charts/discovery-agent/templates/rbac.yaml @@ -110,33 +110,3 @@ subjects: - kind: ServiceAccount name: {{ include "discovery-agent.serviceAccountName" . }} namespace: {{ .Release.Namespace }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "discovery-agent.fullname" . }}-eso-reader - labels: - {{- include "discovery-agent.labels" . | nindent 4 }} -rules: - - apiGroups: ["external-secrets.io"] - resources: - - externalsecrets - - clusterexternalsecrets - - secretstores - - clustersecretstores - verbs: ["get", "list", "watch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "discovery-agent.fullname" . }}-eso-reader - labels: - {{- include "discovery-agent.labels" . | nindent 4 }} -roleRef: - kind: ClusterRole - name: {{ include "discovery-agent.fullname" . }}-eso-reader - apiGroup: rbac.authorization.k8s.io -subjects: - - kind: ServiceAccount - name: {{ include "discovery-agent.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} diff --git a/deploy/charts/discovery-agent/values.schema.json b/deploy/charts/discovery-agent/values.schema.json index 404b9d08..a6c6cb28 100644 --- a/deploy/charts/discovery-agent/values.schema.json +++ b/deploy/charts/discovery-agent/values.schema.json @@ -126,17 +126,17 @@ }, "helm-values.config.clientID": { "default": "", - "description": "Deprecated: Client ID for the configured service account. The client ID should be provided in the \"clientID\" field of the authentication secret (see config.secretName).", + "description": "Deprecated: Client ID for the configured service account. The client ID should be provided in the \"clientID\" field of the authentication secret (see config.secretName). This field is provided for compatibility for users migrating from the \"venafi-kubernetes-agent\" chart.", "type": "string" }, "helm-values.config.clusterDescription": { "default": "", - "description": "A short description of the cluster where the agent is deployed (optional).\n\nThis description will be associated with the data that the agent uploads to the NGTS service. The description may include contact information such as the email address of the cluster administrator.", + "description": "A short description of the cluster where the agent is deployed (optional).\n\nThis description will be associated with the data that the agent uploads to the backend.", "type": "string" }, "helm-values.config.clusterName": { "default": "", - "description": "A human readable name for the cluster where the agent is deployed (required).\n\nThis cluster name will be associated with the data that the agent uploads to the NGTS service.", + "description": "Required: A human readable name for the cluster into which the agent is being deployed.\n\nThis cluster name will be associated with the data that the agent uploads to the backend.", "type": "string" }, "helm-values.config.excludeAnnotationKeysRegex": { @@ -152,23 +152,22 @@ }, "helm-values.config.period": { "default": "0h1m0s", - "description": "Push data every 12 hours unless changed.", + "description": "How often to push data to the remote server", "type": "string" }, "helm-values.config.secretName": { "default": "discovery-agent-credentials", - "description": "The name of the Secret containing the NGTS service account credentials.\nThe Secret must contain the following key:\n- privatekey.pem: PEM-encoded private key for the service account\nThe Secret may contain the following key:\n- clientID: Service account client ID (config.clientID must be set if not present)", + "description": "The name of the Secret containing the NGTS built-in service account credentials.\nThe Secret must contain the following key:\n- privatekey.pem: PEM-encoded private key for the service account\nThe Secret should also contain the following key:\n- clientID: Service account client ID (config.clientID must be set if not present)", "type": "string" }, "helm-values.config.serverURL": { "default": "", - "description": "The NGTS server URL (optional).\nIf not set, a production NGTS server URL will be created based on the tsg ID\nExample: https://ngts.example.com", + "description": "Explicit SCM server URL (optional).\nIf not set, a production SCM server URL will be created based on the TSG ID. This value is intended for development purposes only and should not be set in production.", "type": "string" }, "helm-values.config.tsgID": { "default": "", - "description": "The TSG (Tenant Security Group) ID for your NGTS account (required). NB: TSG IDs are numeric, but must be provided as strings (in double quotes).", - "type": "string" + "description": "Required: The TSG (Tenant Service Group) ID to use when connecting to SCM. NB: TSG IDs are numeric, but should be treated as strings. If being set with the Helm CLI prefer `--set-string`." }, "helm-values.extraArgs": { "default": [], @@ -203,9 +202,6 @@ "pullPolicy": { "$ref": "#/$defs/helm-values.image.pullPolicy" }, - "registry": { - "$ref": "#/$defs/helm-values.image.registry" - }, "repository": { "$ref": "#/$defs/helm-values.image.repository" }, @@ -230,10 +226,6 @@ "description": "This sets the pull policy for images.", "type": "string" }, - "helm-values.image.registry": { - "description": "Deprecated: per-component registry prefix.\n\nIf set, this value is *prepended* to the image repository that the chart would otherwise render. This applies both when `image.repository` is set and when the repository is computed from\n`imageRegistry` + `imageNamespace` + `image.name`.\n\nThis can produce \"double registry\" style references such as\n`legacy.example.io/quay.io/jetstack/...`. Prefer using the global\n`imageRegistry`/`imageNamespace` values.", - "type": "string" - }, "helm-values.image.repository": { "default": "", "description": "Full repository override (takes precedence over `imageRegistry`, `imageNamespace`, and `image.name`).\nExample: quay.io/jetstack/discovery-agent", diff --git a/deploy/charts/discovery-agent/values.yaml b/deploy/charts/discovery-agent/values.yaml index 8440f787..454c2a30 100644 --- a/deploy/charts/discovery-agent/values.yaml +++ b/deploy/charts/discovery-agent/values.yaml @@ -1,6 +1,60 @@ -# Default values for discovery-agent. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. +# Configuration for the Discovery Agent +config: + # Required: The TSG (Tenant Service Group) ID to use when connecting to SCM. + # NB: TSG IDs are numeric, but should be treated as strings. + # If being set with the Helm CLI prefer `--set-string`. + # +docs:property + # +docs:type=string,number + tsgID: "" + + # Required: A human readable name for the cluster into which the agent is being deployed. + # + # This cluster name will be associated with the data that the agent uploads to the backend. + # +docs:property + clusterName: "" + + # A short description of the cluster where the agent is deployed (optional). + # + # This description will be associated with the data that the agent uploads to the backend. + # +docs:property + clusterDescription: "" + + # How often to push data to the remote server + # +docs:property + period: "0h1m0s" + + # You can configure the agent to exclude some annotations or + # labels from being pushed. All Kubernetes objects + # are affected. The objects are still pushed, but the specified annotations + # and labels are removed before being pushed. + # + # Dots is the only character that needs to be escaped in the regex. Use either + # double quotes with escaped single quotes or unquoted strings for the regex + # to avoid YAML parsing issues with `\.`. + # + # Example: excludeAnnotationKeysRegex: ['^kapp\.k14s\.io/original.*'] + excludeAnnotationKeysRegex: [] + excludeLabelKeysRegex: [] + + # Deprecated: Client ID for the configured service account. + # The client ID should be provided in the "clientID" field of the authentication secret (see config.secretName). + # This field is provided for compatibility for users migrating from the "venafi-kubernetes-agent" chart. + # +docs:property + clientID: "" + + # The name of the Secret containing the NGTS built-in service account credentials. + # The Secret must contain the following key: + # - privatekey.pem: PEM-encoded private key for the service account + # The Secret should also contain the following key: + # - clientID: Service account client ID (config.clientID must be set if not present) + # +docs:property + secretName: discovery-agent-credentials + + # Explicit SCM server URL (optional). + # If not set, a production SCM server URL will be created based on the TSG ID. + # This value is intended for development purposes only and should not be set in production. + # +docs:hidden + serverURL: "" # This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ replicaCount: 1 @@ -19,18 +73,6 @@ imageNamespace: "jetstack" # This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ image: - # Deprecated: per-component registry prefix. - # - # If set, this value is *prepended* to the image repository that the chart would otherwise render. - # This applies both when `image.repository` is set and when the repository is computed from - # `imageRegistry` + `imageNamespace` + `image.name`. - # - # This can produce "double registry" style references such as - # `legacy.example.io/quay.io/jetstack/...`. Prefer using the global - # `imageRegistry`/`imageNamespace` values. - # +docs:property - # registry: quay.io - # Full repository override (takes precedence over `imageRegistry`, `imageNamespace`, # and `image.name`). # Example: quay.io/jetstack/discovery-agent @@ -159,62 +201,6 @@ podDisruptionBudget: # +docs:property # maxUnavailable: 1 -# Configuration for the agent -config: - # Push data every 12 hours unless changed. - period: "0h1m0s" - - # You can configure the agent to exclude some annotations or - # labels from being pushed. All Kubernetes objects - # are affected. The objects are still pushed, but the specified annotations - # and labels are removed before being pushed. - # - # Dots is the only character that needs to be escaped in the regex. Use either - # double quotes with escaped single quotes or unquoted strings for the regex - # to avoid YAML parsing issues with `\.`. - # - # Example: excludeAnnotationKeysRegex: ['^kapp\.k14s\.io/original.*'] - excludeAnnotationKeysRegex: [] - excludeLabelKeysRegex: [] - - # A human readable name for the cluster where the agent is deployed (required). - # - # This cluster name will be associated with the data that the agent uploads to - # the NGTS service. - clusterName: "" - - # A short description of the cluster where the agent is deployed (optional). - # - # This description will be associated with the data that the agent uploads to - # the NGTS service. The description may include contact - # information such as the email address of the cluster administrator. - clusterDescription: "" - - # Deprecated: Client ID for the configured service account. - # The client ID should be provided in the "clientID" field of the authentication secret (see config.secretName). - # +docs:property - clientID: "" - - # The TSG (Tenant Security Group) ID for your NGTS account (required). - # NB: TSG IDs are numeric, but must be provided as strings (in double quotes). - # +docs:property - # +docs:type=string - tsgID: "" - - # The name of the Secret containing the NGTS service account credentials. - # The Secret must contain the following key: - # - privatekey.pem: PEM-encoded private key for the service account - # The Secret may contain the following key: - # - clientID: Service account client ID (config.clientID must be set if not present) - # +docs:property - secretName: discovery-agent-credentials - - # The NGTS server URL (optional). - # If not set, a production NGTS server URL will be created based on the tsg ID - # Example: https://ngts.example.com - # +docs:hidden - serverURL: "" - # extraArgs: # - --logging-format=json # - --log-level=6 # To enable HTTP request logging diff --git a/deploy/charts/venafi-kubernetes-agent/templates/_helpers.tpl b/deploy/charts/venafi-kubernetes-agent/templates/_helpers.tpl index 62e627a4..5d781866 100644 --- a/deploy/charts/venafi-kubernetes-agent/templates/_helpers.tpl +++ b/deploy/charts/venafi-kubernetes-agent/templates/_helpers.tpl @@ -62,10 +62,8 @@ Create the name of the service account to use {{- end }} {{/* -Util function for generating the image URL based on the provided options. -IMPORTANT: This function is standardized across all charts in the cert-manager GH organization. -Any changes to this function should also be made in cert-manager, trust-manager, approver-policy, ... -See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linked PRs. +Util function for generating an image reference based on the provided options. +This function is derviced from similar functions used in the cert-manager GitHub organization */}} {{- define "image" -}} {{- /* diff --git a/hack/ark/test-e2e.sh b/hack/ark/test-e2e.sh index 2c1bb241..b96a43a9 100755 --- a/hack/ark/test-e2e.sh +++ b/hack/ark/test-e2e.sh @@ -128,17 +128,17 @@ timeout 60 jq -n \ # Query the Prometheus metrics endpoint to ensure it's working. kubectl get pod \ - --namespace cyberark \ + --namespace $NAMESPACE \ --selector app.kubernetes.io/name=disco-agent \ --output jsonpath={.items[*].metadata.name} \ - | xargs -I{} kubectl get --raw /api/v1/namespaces/cyberark/pods/{}:8081/proxy/metrics \ + | xargs -I{} kubectl get --raw /api/v1/namespaces/$NAMESPACE/pods/{}:8081/proxy/metrics \ | grep '^process_' # Query the pprof endpoint to ensure it's working. kubectl get pod \ - --namespace cyberark \ + --namespace $NAMESPACE \ --selector app.kubernetes.io/name=disco-agent \ --output jsonpath={.items[*].metadata.name} \ - | xargs -I{} kubectl get --raw /api/v1/namespaces/cyberark/pods/{}:8081/proxy/debug/pprof/cmdline \ + | xargs -I{} kubectl get --raw /api/v1/namespaces/$NAMESPACE/pods/{}:8081/proxy/debug/pprof/cmdline \ | xargs -0 diff --git a/hack/ngts/custom_ca.yaml b/hack/ngts/custom_ca.yaml new file mode 100644 index 00000000..f0c9849f --- /dev/null +++ b/hack/ngts/custom_ca.yaml @@ -0,0 +1,12 @@ +# These values are used to set a custom CA bundle during the NGTS test. +# Only used when developing locally, as detected by logic in test-e2e.sh + +volumes: +- name: custom-ca-volume + configMap: + name: custom-ca + +volumeMounts: +- name: custom-ca-volume + mountPath: /etc/ssl/certs + diff --git a/hack/ngts/test-e2e.sh b/hack/ngts/test-e2e.sh index 99043033..3bfae452 100755 --- a/hack/ngts/test-e2e.sh +++ b/hack/ngts/test-e2e.sh @@ -56,17 +56,61 @@ fi kubectl create ns "$NAMESPACE" || true -kubectl delete secret agent-credentials --namespace "$NAMESPACE" --ignore-not-found -kubectl create secret generic agent-credentials \ +kubectl delete secret discovery-agent-credentials --namespace "$NAMESPACE" --ignore-not-found +kubectl create secret generic discovery-agent-credentials \ --namespace "$NAMESPACE" \ - --from-literal=CLIENT_ID=$NGTS_CLIENT_ID \ - --from-literal=PRIVATE_KEY="$NGTS_PRIVATE_KEY" + --from-literal=clientID=$NGTS_CLIENT_ID \ + --from-literal=privatekey.pem="$NGTS_PRIVATE_KEY" # Create a sample secret in the cluster kubectl create secret generic e2e-sample-secret-$(date '+%s') \ --namespace default \ --from-literal=username=${RANDOM} +# Create values.yaml file for the helm chart +cat > "${tmp_dir}/values.yaml" < $CA_BUNDLE_FILE + + kubectl create configmap custom-ca --namespace="$NAMESPACE" --from-file=ca_certs.crt="$CA_BUNDLE_FILE" + + # Need to update values.yaml to add the custom CA bundle + custom_ca_yaml="${script_dir}/custom_ca.yaml" + yq eval-all '. as $item ireduce ({}; . * $item)' "${tmp_dir}/values.yaml" "$custom_ca_yaml" > "${tmp_dir}/values.merged.yaml" + mv "${tmp_dir}/values.merged.yaml" "${tmp_dir}/values.yaml" +fi + # We use a non-existent tag and omit the `--version` flag, to work around a Helm # v4 bug. See: https://github.com/helm/helm/issues/31600 helm upgrade agent "oci://${NGTS_CHART}:NON_EXISTENT_TAG@${NGTS_CHART_DIGEST}" \ @@ -74,38 +118,30 @@ helm upgrade agent "oci://${NGTS_CHART}:NON_EXISTENT_TAG@${NGTS_CHART_DIGEST}" \ --wait \ --create-namespace \ --namespace "$NAMESPACE" \ - --set-json extraArgs='["--log-level=6"]' \ - --set pprof.enabled=true \ - --set fullnameOverride=discovery-agent \ - --set "imageRegistry=${OCI_BASE}" \ - --set "imageNamespace=" \ - --set "image.digest=${NGTS_IMAGE_DIGEST}" \ - --set config.clusterName="e2e-test-cluster" \ - --set config.clusterDescription="A temporary cluster for E2E testing." \ - --set config.period=60s \ - --set ngts.tsgId="${NGTS_TSG_ID}" \ - --set-json "podLabels={\"discovery-agent.ngts/test-id\": \"${RANDOM}\"}" + --values "${tmp_dir}/values.yaml" kubectl rollout status deployments/discovery-agent --namespace "${NAMESPACE}" -# Wait 60s for log message indicating success. +# Wait for log message indicating success. # Parse logs as JSON using jq to ensure logs are all JSON formatted. -timeout 60 jq -n \ +timeout 120 jq -n \ 'inputs | if .msg | test("Data sent successfully") then . | halt_error(0) else . end' \ <(kubectl logs deployments/discovery-agent --namespace "${NAMESPACE}" --follow) # Query the Prometheus metrics endpoint to ensure it's working. kubectl get pod \ - --namespace ngts \ + --namespace ${NAMESPACE} \ --selector app.kubernetes.io/name=discovery-agent \ --output jsonpath={.items[*].metadata.name} \ - | xargs -I{} kubectl get --raw /api/v1/namespaces/ngts/pods/{}:8081/proxy/metrics \ + | xargs -I{} kubectl get --raw /api/v1/namespaces/$NAMESPACE/pods/{}:8081/proxy/metrics \ | grep '^process_' # Query the pprof endpoint to ensure it's working. kubectl get pod \ - --namespace ngts \ + --namespace ${NAMESPACE} \ --selector app.kubernetes.io/name=discovery-agent \ --output jsonpath={.items[*].metadata.name} \ - | xargs -I{} kubectl get --raw /api/v1/namespaces/ngts/pods/{}:8081/proxy/debug/pprof/cmdline \ + | xargs -I{} kubectl get --raw /api/v1/namespaces/$NAMESPACE/pods/{}:8081/proxy/debug/pprof/cmdline \ | xargs -0 + +# TODO: should call to SCM and verify that certs are actually uploaded diff --git a/make/ngts/02_mod.mk b/make/ngts/02_mod.mk index c501d8d0..12492fe7 100644 --- a/make/ngts/02_mod.mk +++ b/make/ngts/02_mod.mk @@ -40,7 +40,7 @@ ngts-release: ## Run a basic E2E test on a Kind cluster ## See `hack/ngts/e2e.sh` for the full test script. ## @category NGTS Discovery Agent -ngts-test-e2e: $(NEEDS_KIND) $(NEEDS_KUBECTL) $(NEEDS_HELM) +ngts-test-e2e: $(NEEDS_KIND) $(NEEDS_KUBECTL) $(NEEDS_HELM) $(NEEDS_YQ) PATH="$(bin_dir)/tools:${PATH}" ./hack/ngts/test-e2e.sh .PHONY: ngts-verify diff --git a/pkg/client/client_ngts.go b/pkg/client/client_ngts.go index b71f65d0..8de67901 100644 --- a/pkg/client/client_ngts.go +++ b/pkg/client/client_ngts.go @@ -80,11 +80,9 @@ const ( ngtsUploadEndpoint = "v1/tlspk/upload/clusterdata/no" // ngtsAccessTokenEndpoint matches the CM-SaaS token endpoint - // TODO: Confirm that this will match in NGTS ngtsAccessTokenEndpoint = accessTokenEndpoint // ngtsRequiredGrantType matches the CM-SaaS required grant type for JWTs - // TODO: Confirm JWT structure for NGTS ngtsRequiredGrantType = requiredGrantType ) @@ -166,30 +164,32 @@ func (c *NGTSServiceAccountCredentials) LoadClientIDIfNeeded() error { return fmt.Errorf("credentials are nil") } - // If ClientID is already set, nothing to do + // If ClientID is already set via helm values / CLI args, nothing to do if c.ClientID != "" { + klog.V(2).Info("Using clientID from config.clientID helm value") return nil } + // We'd preferably have NGTSServiceAccountCredentials.CredentialPath but we didn't want to make another change + // to existing CLI flags; so we depend on PrivateKeyFile and assume clientID is in the same directory. + // If PrivateKeyFile is not set, we can't determine where to look for the clientID file if c.PrivateKeyFile == "" { - return nil // Will be caught by Validate() later + return nil // This is actually a fatal error but will be caught by Validate() later } // Try to load ClientID from a file in the same directory as the private key clientIDPath := path.Dir(c.PrivateKeyFile) + "/clientID" clientIDBytes, err := os.ReadFile(clientIDPath) if err != nil { - // If the file doesn't exist, that's okay - the ClientID might be required to be set directly - if os.IsNotExist(err) { - return nil - } - return fmt.Errorf("failed to read clientID from %s: %w", clientIDPath, err) + // If the file doesn't exist, that's okay - we'll let Validate() catch the empty ClientID error later + klog.V(2).Info("Could not read clientID from file", "path", clientIDPath, "error", err) + return nil } // Trim whitespace from the clientID c.ClientID = strings.TrimSpace(string(clientIDBytes)) - klog.V(2).Info("Loaded clientID from secret file", "path", clientIDPath) + klog.V(2).Info("Loaded clientID from file", "path", clientIDPath) return nil } @@ -205,7 +205,7 @@ func (c *NGTSServiceAccountCredentials) Validate() error { } if c.PrivateKeyFile == "" { - return fmt.Errorf("private_key_file cannot be empty") + return fmt.Errorf("NGTS private key file location cannot be empty") } return nil