Prisma Cloud の CWPP の開始 (w/Minikube)

## やること

* Prisma Cloudの開始
* Defender AgentをMinikubeにインストール
* Auth0(SAML IdP)でSSO + JITP

## Prisma Cloud

[https://www.paloaltonetworks.jp/prisma/cloud](https://www.paloaltonetworks.jp/prisma/cloud) より

> Prisma Cloudにより、ハイブリッド環境やマルチクラウド環境全体にわたってインフラストラクチャ、アプリケーション、データを保護

### CWPPの定義

[改めて知るCWPP（Cloud Workload Protection Platform）とは何か？](https://www.macnica.co.jp/business/dx/manufacturers/prisma/feature_01.html) より

> Gartnerでは「2021 Gartner Market Guide for CWPP」の中で、CWPPを以下のように定義しています。
> "workload-centric security products that protect server workloads in hybrid, multicloud data center environments."
> 様々なクラウド環境におけるサーバワークロードを保護する、ワークロード中心のセキュリティ製品ということですが、上記でワークロードの種別をご紹介したとおり、ワークロード自体も多様になっていますので、「多様なクラウド環境における多様なワークロードに対して一貫した可視化とコントロールができること」がCWPPの果たすべき役割だと考えています。クラウド環境自体もハイブリッドクラウド・マルチクラウド化が進んできていますので、これらにシームレスに対応できるかも重要なポイントです。
> また、クラウドネイティブなアプリケーション環境においては、開発パイプラインの中で事前にワークロードに含まれ得るリスク（脆弱性やコンプライアンス違反等）をスキャンできることも重要になります。この点は特に、多くの企業にとって従来型のサーバ向けセキュリティ製品と大きく位置づけが異なると感じられるポイントではないかと思います。

### CWPPが提供する機能

> * Development Scanning（開発段階でのスキャン）
>    * コンポーネントに含まれる脆弱性
>    * クラウド設定状況
>    * シークレットの含有状況
>    * マルウェアの含有状況
>    * API
> * Runtime Protection（ランタイム保護）
>    * コンポーネントに含まれる脆弱性
>    * クラウド設定状況
>    * シークレットの含有状況
>    * マルウェアの含有状況
>    * API

## はじめる

* AWS Marketplaceから利用開始できる。
* SaaS形式なので、EC2が立ち上がったりはしない。
* 15日間は無料らしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/f31aeb6f-801f-5174-f2f4-2af763910e12.png)

## アカウント作成後の初回ログイン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/bb253b80-11ae-2181-8e51-c19d04cfbc5e.png)

## Defenderのインストール

Compute > Defenders > Deploy > Defenders

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/bae12055-ed5c-d75a-aa54-2535394dffb2.png)

設定値を入れる。（OpenShiftで使うときは色々変えないとね。）

1. Deployment method -> Orchestrator
1. Choose the orchestrator type -> Kubernetes
1. The name that Defender will use to connect to this Console -> 変更なし
1. Specify a proxy for the defender -> Off
1. Assign globally unique names to Hosts -> Off
1. Specify a cluster name -> minikube
1. Enter the namespace of the Defender Daemon Set -> twistlock
1. NodeSelector -> 空欄
1. Specify a custom docker socket path -> 空欄
1. Monitor service accounts -> On
1. Minitor Istio -> On
1. Collect Deployment and Namespace labels -> Off
1. Use the official Twistlock registry -> On
1. Deploy Defenders with SELinux Policy -> Off
1. Run Defenders as privileged -> Off
1. Nodes use Container Runtime Interface (CRI), not Docker -> Off
1. Nodes run inside containerized environment -> Off
1. Install the Defender Daemon Set in the Kubernetes cluster using one of the following options: -> YAML

以下のYAMLがゲットできる。

```yaml:daemonset.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: twistlock-view
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"] # Allow Defenders to list RBAC resources
  verbs: ["list"]
- apiGroups: ["security.istio.io"]
  resources: ["authorizationpolicies", "peerauthentications"] # Allow Defenders to list Istio security resources
  verbs: ["list"]
- apiGroups: ["networking.istio.io"]
  resources: ["virtualservices", "destinationrules", "gateways"] # Allow Defenders to list Istio networking resources
  verbs: ["list"]
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods", "endpoints", "services"] # Allow Defenders to list pods, services and endpoints
  verbs: ["list"]
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods/proxy"] # Allow Defenders to get pod proxy
  verbs: ["get"]
---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: twistlock-view-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: twistlock-view
subjects:
- apiGroup:
  kind: ServiceAccount
  name: twistlock-service
  namespace: twistlock
---

---
apiVersion: v1
kind: Secret
metadata:
  name: twistlock-secrets
  namespace: twistlock
type: Opaque
data:

...snip...

---
apiVersion: v1
kind: ServiceAccount # Service Account is used for managing security context constraints policies in Openshift (SCC)
metadata:
  name: twistlock-service
  namespace: twistlock
secrets:
- name: twistlock-secrets
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: twistlock-defender-ds
  namespace: twistlock
spec:
  selector:
    matchLabels:
      app: twistlock-defender
  template:
    metadata:
      annotations:
        container.apparmor.security.beta.kubernetes.io/twistlock-defender: unconfined
      labels:
        app: twistlock-defender
    spec:
      serviceAccountName: twistlock-service
      restartPolicy: Always
      containers:
      - name: twistlock-defender
        image: registry-auth.twistlock.com/tw_oqaszoiyuey3cfd4hodmxu1sytzgbeiy/twistlock/defender:defender_22_01_880
        volumeMounts:
        - name: data-folder
          mountPath: "/var/lib/twistlock"
        - name: certificates # Setting the certificates mount after data-folder since it is nested and was overridden in CRI based GKE cluster
          mountPath: "/var/lib/twistlock/certificates"
        - name: docker-sock-folder
          mountPath: "/var/run"
        - name: passwd
          mountPath: "/etc/passwd"
          readOnly: true
        - name: syslog-socket
          mountPath: "/dev/log"
        env:
        - name: WS_ADDRESS
          value: wss://australia-southeast1.cloud.twistlock.com:443
        - name: DEFENDER_TYPE
          value: daemonset
        - name: DEFENDER_LISTENER_TYPE
          value: "none"
        - name: LOG_PROD
          value: "true"
        - name: SYSTEMD_ENABLED
          value: "false"
        - name: DOCKER_CLIENT_ADDRESS
          value: "/var/run/docker.sock"
        - name: DEFENDER_CLUSTER_ID
          value: "...snip..."
        - name: DEFENDER_CLUSTER
          value: "minikube"
        - name: MONITOR_SERVICE_ACCOUNTS
          value: "true"
        - name: MONITOR_ISTIO
          value: "true"
        - name: COLLECT_POD_LABELS
          value: "false"
        - name: INSTALL_BUNDLE
          value: "...snip..."
        - name: HOST_CUSTOM_COMPLIANCE_ENABLED
          value: "false"
        - name: CLOUD_HOSTNAME_ENABLED
          value: "false"
        securityContext:
          readOnlyRootFilesystem: true
          privileged: false
          capabilities:
            add:
            - NET_ADMIN  # Required for process monitoring
            - NET_RAW    # Required for iptables (CNNF, runtime DNS, WAAS). See: https://bugzilla.redhat.com/show_bug.cgi?id=1895032
            - SYS_ADMIN  # Required for filesystem monitoring
            - SYS_PTRACE # Required for local audit monitoring
            - SYS_CHROOT # Required for changing mount namespace using setns
            - MKNOD      # A capability to create special files using mknod(2), used by docker-less registry scanning
            - SETFCAP    # A capability to set file capabilities, used by docker-less registry scanning
            - IPC_LOCK   # Required for perf events monitoring, allowing to ignore memory lock limits
        resources: # See: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#how-pods-with-resource-requests-are-scheduled
          limits:
            memory: "512Mi"
            cpu: "900m"
          requests:
            cpu: "256m"
      volumes:
      - name: certificates
        secret:
          secretName: twistlock-secrets
          defaultMode: 256
      - name: syslog-socket
        hostPath:
          path: "/dev/log"
      - name: data-folder
        hostPath:
          path: "/var/lib/twistlock"
      - name: passwd
        hostPath:
          path: "/etc/passwd"
      - name: docker-sock-folder
        hostPath:
          path: "/var/run"
      hostPID: true
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
---
apiVersion: v1
kind: Service # Expose the Defender as admission controller. Remark: by default, Defender will not listen on the service port
metadata:
  name: defender
  namespace: twistlock
  labels:
    app: twistlock-defender
spec:
  ports:
  - port: 443
    targetPort: 9998
  selector:
    app: twistlock-defender
```

ns作って、yamlを放り込む。

```bash
$ kubectl create ns twistlock
namespace/twistlock created
$ kubectl -n twistlock apply -f ./defender.yaml 
clusterrole.rbac.authorization.k8s.io/twistlock-view created
clusterrolebinding.rbac.authorization.k8s.io/twistlock-view-binding created
secret/twistlock-secrets created
serviceaccount/twistlock-service created
daemonset.apps/twistlock-defender-ds created
service/defender created
$ kubectl -n twistlock get pod
NAME                          READY   STATUS    RESTARTS   AGE
twistlock-defender-ds-gcjh9   1/1     Running   0          81s
```

Compute > Radars > Containers
でなにか見えるようになる。（bookinfoばかり適当に突っ込んだ残骸が見える）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/f8abddf7-dc99-1b06-cd4d-3f8e024c1c26.png)

## 散策

### Radar > Hosts

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/1b49d79e-0fed-aec0-b66e-160460102f68.png)

### Radar > Containers

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/02b85a7c-0f8d-5406-ad37-3847453e5100.png)

### Monitor > Runtimes

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/75c19089-b481-dbae-50c0-1a00bb6b9769.png)

### Monitor > Vulnerabilities

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/774985d7-fe5d-0ac2-7e3d-d7b00ad411c8.png)
### Monitor > Compliance

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/b2e433fa-7ace-9c03-84a1-4980fca61980.png)

## SAML SSO + JITP

Auth0でSAMLでSSOする。

Auth0側では、**Addon: SAML2 Web App**を有効にして、
Callback URLを`https://api.anz.prismacloud.io/saml`にする。

Prisma Cloud側では、Settings > Access Control > SSO に行く。設定を入れる。
JITPするが、ここでは動作確認だけするので、Auth0側の既定の属性セットを無理やり設定する。

1. Enable SSO > On
1. Audience URI -> 変更なし
1. Identity Provider Issuer -> urn:thousandth.auth0.com
1. Identity Provider Logout URL -> 空欄
1. Certificate -> Auth0からDLしたPEMを貼る
1. Prisma Cloud Access SAML URL -> 空欄
1. Relay State Param Name -> 空欄
1. Enforce DNS resolution for Prisma Cloud Access SAML URL -> Off
1. Enable JIT Provisioning -> On
1. Email -> http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
1. Role -> http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
1. First Name -> http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
1. Last Name -> http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn
1. Allow select users to authenticate directly with Prisma Cloud -> アカウント登録時のメールアドレス

ログイン試行するユーザのnameidentifierでRoleを作っておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/05db278d-1a56-5148-5266-6e77bf02ac4c.png)

Auth0側のSettingsを以下のように変更。

```json
{
{
  "audience": "https://app.anz.prismacloud.io/customer/7eb ...snip... e70",
  "nameIdentifierProbes": [
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
  ]
}
```

IdP Initiated SSOして、JITPもでてきて、RoleへのBindingも成功した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/afe04072-447b-0d84-996c-14f09b6d65e0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/c07d2164-7fa9-e075-4e43-704b85ab6f3a.png)

Read Onlyも効いてそう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325101/14bce7f7-d571-7d6f-f684-11244de95f19.png)

### JITPでのRole Bindingについて

* Prisma Cloudで予め作ったRoleにBindingする仕様
* 「Assertionに含まれる属性値がAだったら、RoleはX」みたいな読み替えはできない。RoleでBindすると定義した属性値がそのままRoleになる。（たぶん）
* ただ、Prisma CloudはRoleのスイッチが可能。複数RoleへのBindingをJITP時にやるにはどうしたらええんやろ。

## 自分用メモ

* System AdminはSAML対象のユーザではないので、違うブラウザのPassword Credentialを用いてログインすること。