# 安裝後調整
## 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
```