# 安裝後調整 ## TAP-GUI ``` kubectl create secret tls tap-gui-cert \ --cert=~/contour/tap1/server.crt \ --key=~/contour/tap1/server.key \ -n tap-gui ``` ``` cat << EOF | kubectl apply -f - apiVersion: v1 kind: Namespace metadata: name: tap-gui --- apiVersion: v1 kind: ServiceAccount metadata: namespace: tap-gui name: tap-gui-viewer --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: tap-gui-read-k8s subjects: - kind: ServiceAccount namespace: tap-gui name: tap-gui-viewer roleRef: kind: ClusterRole name: k8s-reader apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: k8s-reader rules: - apiGroups: [''] resources: ['pods', 'pods/log', 'services', 'configmaps', 'limitranges'] verbs: ['get', 'watch', 'list'] - apiGroups: ['metrics.k8s.io'] resources: ['pods'] verbs: ['get', 'watch', 'list'] - apiGroups: ['apps'] resources: ['deployments', 'replicasets', 'statefulsets', 'daemonsets'] verbs: ['get', 'watch', 'list'] - apiGroups: ['autoscaling'] resources: ['horizontalpodautoscalers'] verbs: ['get', 'watch', 'list'] - apiGroups: ['networking.k8s.io'] resources: ['ingresses'] verbs: ['get', 'watch', 'list'] - apiGroups: ['networking.internal.knative.dev'] resources: ['serverlessservices'] verbs: ['get', 'watch', 'list'] - apiGroups: [ 'autoscaling.internal.knative.dev' ] resources: [ 'podautoscalers' ] verbs: [ 'get', 'watch', 'list' ] - apiGroups: ['serving.knative.dev'] resources: - configurations - revisions - routes - services verbs: ['get', 'watch', 'list'] - apiGroups: ['carto.run'] resources: - clusterconfigtemplates - clusterdeliveries - clusterdeploymenttemplates - clusterimagetemplates - clusterruntemplates - clustersourcetemplates - clustersupplychains - clustertemplates - deliverables - runnables - workloads verbs: ['get', 'watch', 'list'] - apiGroups: ['source.toolkit.fluxcd.io'] resources: - gitrepositories verbs: ['get', 'watch', 'list'] - apiGroups: ['source.apps.tanzu.vmware.com'] resources: - imagerepositories - mavenartifacts verbs: ['get', 'watch', 'list'] - apiGroups: ['conventions.apps.tanzu.vmware.com'] resources: - podintents verbs: ['get', 'watch', 'list'] - apiGroups: ['kpack.io'] resources: - images - builds verbs: ['get', 'watch', 'list'] - apiGroups: ['scanning.apps.tanzu.vmware.com'] resources: - sourcescans - imagescans - scanpolicies - scantemplates verbs: ['get', 'watch', 'list'] - apiGroups: ['app-scanning.apps.tanzu.vmware.com'] resources: - imagevulnerabilityscans verbs: ['get', 'watch', 'list'] - apiGroups: ['tekton.dev'] resources: - taskruns - pipelineruns verbs: ['get', 'watch', 'list'] - apiGroups: ['kappctrl.k14s.io'] resources: - apps verbs: ['get', 'watch', 'list'] - apiGroups: [ 'batch' ] resources: [ 'jobs', 'cronjobs' ] verbs: [ 'get', 'watch', 'list' ] - apiGroups: ['conventions.carto.run'] resources: - podintents verbs: ['get', 'watch', 'list'] - apiGroups: ['appliveview.apps.tanzu.vmware.com'] resources: - resourceinspectiongrants verbs: ['get', 'watch', 'list', 'create'] EOF ``` ``` CLUSTER_URL=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}') kubectl apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: tap-gui-viewer namespace: tap-gui annotations: kubernetes.io/service-account.name: tap-gui-viewer type: kubernetes.io/service-account-token EOF CLUSTER_TOKEN=$(kubectl -n tap-gui get secret tap-gui-viewer -o=json \ | jq -r '.data["token"]' \ | base64 --decode) echo CLUSTER_URL: $CLUSTER_URL echo CLUSTER_TOKEN: $CLUSTER_TOKEN ``` update tap-values.yaml ``` tap_gui: tls: namespace: tap-gui secretName: tap-gui-cert app-config: kubernetes: serviceLocatorMethod: type: multiTenant clusterLocatorMethods: - type: 'config' clusters: - url: $CLUSTER_URL name: tap1 authProvider: serviceAccount skipTLSVerify: true serviceAccountToken: $CLUSTER_TOKEN ``` ``` tanzu package installed update tap -n tap-install --values-file=tap-values.yaml tanzu package installed get tap-gui -n tap-install ``` ## Grype Integration with Namespace-Provisioner ### 1. Create Grype-DB ``` kubectl create ns grype-db kubectl create deployment grype-db \ --image nginx \ -n grype-db kubectl expose deployment grype-db -n grype-db \ --type=NodePort \ --name=grype-db-service \ --port=80 kubectl apply -f ingress.yaml -n grype-db (optional) ``` ### 2. Apply a grype-package-overlay 當透過 namespace provisioner 的方式去創造一個新的開發者所使用的 namespace 時,此時會自動 create 一個新的 package. 例如 - grype-scanner-namespace - grype-scanner-tap-dev0 - grype-scanner-dev1 而此時,我們可以透過 annotations 告訴這些 package,當我只要找到 >> 1. apiVersion 是 "packaging.carverl.dev/v1alpha1". >> 2. metadata 是 grype-scanner 開頭的物件時. 我就要應用一個 overlay,overlay 的名字叫做 "tim-grype-overlay-secret". ``` cat << EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: grype-package-overlay namespace: tap-install annotations: kapp.k14s.io/change-rule: "delete after deleting tap" stringData: grype-package-overlay.yaml: | #@ load("@ytt:overlay", "overlay") #@ #@ def matchGrypeScanners(index, left, right): #@ if left["apiVersion"] != "packaging.carvel.dev/v1alpha1" or left["kind"] != "PackageInstall": #@ return False #@ end #@ return "metadata" in left and "name" in left["metadata"] and left["metadata"]["name"].startswith("grype-scanner") #@ end #@overlay/match by=matchGrypeScanners, expects="0+" --- metadata: annotations: #@overlay/match expects="0+" ext.packaging.carvel.dev/ytt-paths-from-secret-name.0: tim-grype-overlay-secret EOF ``` ### 3. Apply a grype-overlay scantemplate 會使用此 overlay 覆蓋掉原本的 scantemplate,以使用我們剛剛於第一步驟創造的 grype-db service url. ``` cat << EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: tim-grype-overlay-secret namespace: tap-install #! namespace where tap is installed stringData: patch.yaml: | #@ load("@ytt:overlay", "overlay") #@overlay/match by=overlay.subset({"kind":"ScanTemplate"}),expects="1+" --- spec: template: initContainers: #@overlay/match by=overlay.subset({"name": "scan-plugin"}), expects="1+" - name: scan-plugin #@overlay/match missing_ok=True env: #@overlay/append - name: GRYPE_CHECK_FOR_APP_UPDATE value: "false" - name: GRYPE_DB_AUTO_UPDATE value: "true" - name: GRYPE_DB_UPDATE_URL value: http://grype-db-svc.grype-db/listing.json - name: GRYPE_DB_MAX_ALLOWED_BUILT_AGE value: "12000h" EOF ``` ### 4. 更新 tap-values ``` namespace_provisioner: controller: true overlay_secrets: - name: grype-package-overlay namespace: tap-install create_export: true ``` ``` tanzu package installed update tap -n tap-install --values-file=tap-values.yaml tanzu package installed get namespace-provisioner -n tap-install ``` ``` kubectl get secret -n tap-namespace-provisioning ``` ### 5. 確認是否成功 ``` kubectl create ns tap-dev kubectl label ns tap-dev apps.tanzu.vmware.com/tap-ns='yes' ``` Check if the scantemplate is updated or not ``` kubectl get scantemplate -n tap-dev private-image-scan-template -oyaml ``` ## Grype DB Update ``` ./grype_offline.sh 'http://grype-db-service.grype-db' # 將下載的 tar.gz 以及修改過的 listing.json 複製到容器內 kubectl cp ./ \ grype-db/grype-db-7cd95446c5-b52jc:/usr/share/nginx/html/ \ -n grype-db # 確認是否成功 curl http://grype-db.tap1.tanzu.tim.lab/listing.json ``` ## Add Source Scan to the SupplyChain ``` cat << EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: ootb-supply-chain-testing-scanning-add-source-scanner namespace: tap-install annotations: kapp.k14s.io/change-group: "tap-overlays" type: Opaque stringData: ootb-supply-chain-testing-scanning-add-source-scanner.yaml: | #@ load("@ytt:overlay", "overlay") #@ load("@ytt:data", "data") #@overlay/match by=overlay.subset({"metadata":{"name":"source-test-scan-to-url"}, "kind": "ClusterSupplyChain"}) --- spec: resources: #@overlay/match by=overlay.index(2) #@overlay/insert before=True - name: source-scanner params: - default: scan-policy name: scanning_source_policy - default: blob-source-scan-template name: scanning_source_template sources: - name: source resource: source-tester templateRef: kind: ClusterSourceTemplate name: source-scanner-template #@overlay/match by=overlay.subset({"name": "image-provider"}), expects="1+" - #@overlay/match missing_ok=True sources: #@overlay/match by=overlay.subset({"name": "source"}), expects="1+" - #@overlay/match missing_ok=True resource: source-scanner EOF ``` update tap-values.yaml ``` package_overlays: - name: ootb-supply-chain-testing-scanning secrets: - name: ootb-supply-chain-testing-scanning-add-source-scanner ``` update tap ``` tanzu package installed update tap -n tap-install --values-file=tap-values.yaml ``` ## Metadata-store Metadata Store 用來存放 Vulnerabilties 的資料, TAP full 有內建一組 web server (namespace: metadata-store). 但需要設定相關的 RBAC 後, 方可於 TAP-GUI 介面呈現. ``` AUTH_TOKEN=$(kubectl get secret -n metadata-store metadata-store-read-write-client -otemplate='{{.data.token | base64decode}}') ``` update tap-values.yaml ``` tap_gui: proxy: /metadata-store: target: https://metadata-store-app.metadata-store:8443/api/v1 changeOrigin: true secure: false headers: Authorization: "Bearer $AUTH_TOKEN" X-Custom-Source: project-star ``` update tap ``` tanzu package installed update tap -n tap-install --values-file=tap-values.yaml ``` ## GitOps Secret for FluxCD 需要將此 secret 放在 namespace-provisioner 中,其中必須包含 username/password/caFile,並給予service account 相對權限。 https://gitlab.apps.tanzu.tim.lab/tapadmin/namespace-provisioner/-/blob/main/custom-resources/workload-sa/workload-sa-with-secret.yaml ``` #@ load("@ytt:base64", "base64") --- apiVersion: v1 kind: Secret metadata: name: github-workload-token annotations: tekton.dev/git-0: https://gitlab.apps.tanzu.tim.lab/ type: kubernetes.io/basic-auth stringData: username: tapadmin password: glpat-xxxxxxxxxx caFile: | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: workload-sa-permit-deliverable roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: deliverable subjects: - kind: ServiceAccount name: workload-sa --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: workload-sa-permit-workload roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: workload subjects: - kind: ServiceAccount name: workload-sa --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: contour rules: - apiGroups: - "" resources: - endpoints - namespaces - secrets - services verbs: - get - list - watch - apiGroups: - gateway.networking.k8s.io resources: - gatewayclasses - gateways - grpcroutes - httproutes - referencegrants - tlsroutes verbs: - get - list - watch - apiGroups: - gateway.networking.k8s.io resources: - gatewayclasses/status - gateways/status - grpcroutes/status - httproutes/status - tlsroutes/status verbs: - update - apiGroups: - networking.k8s.io resources: - ingresses verbs: - get - list - watch - create - update - apiGroups: - networking.k8s.io resources: - ingresses/status verbs: - create - get - update - apiGroups: - projectcontour.io resources: - contourconfigurations - extensionservices - httpproxies - tlscertificatedelegations verbs: - get - list - watch - apiGroups: - projectcontour.io resources: - contourconfigurations/status - extensionservices/status - httpproxies/status verbs: - create - get - update - apiGroups: - "" resources: - events verbs: - create - get - update - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: contour-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: contour subjects: - kind: ServiceAccount name: default --- ``` 最後要將此 secret 授予讓 service account 可以使用。 https://gitlab.apps.tanzu.tim.lab/tapadmin/namespace-provisioner/-/blob/main/default-resources-overrides/overlays/workload-sa.lib.yml ``` #@ load("@ytt:overlay", "overlay") #@ def customize(): #! rewrite the workload-sa serviceaccount secrets/ requires gitlab-workload-token and github-workload-token secrets from /custom-resources/workload-sa/workload-sa-with-secrets.yaml #@overlay/match by=overlay.subset({"apiVersion": "v1", "kind": "ServiceAccount","metadata":{"name":"workload-sa"}}), expects="0+" --- secrets: - name: github-workload-token - name: registries-credentials - name: cosign imagePullSecrets: - name: github-workload-token - name: registries-credentials #@ end ```