---
# System prepended metadata

title: 安裝後調整

---

# 安裝後調整

## 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

```