├── .gitignore ├── .gitattributes ├── src ├── workloads │ ├── argocd │ │ ├── base │ │ │ └── argocd-namespace.yaml │ │ ├── overlays │ │ │ ├── argocd-rbac-cm.yaml │ │ │ ├── argocd-server-service.yaml │ │ │ └── argocd-cm.yaml │ │ └── kustomization.yaml │ ├── super-awesome-app │ │ ├── all │ │ │ ├── base │ │ │ │ ├── namespace.yaml │ │ │ │ ├── petclinic-java-injector.yaml │ │ │ │ ├── netflicks-net-injector.yaml │ │ │ │ ├── netflicks-net-service.yaml │ │ │ │ ├── petclinic-java-deployment.yaml │ │ │ │ └── netflicks-net-deployment.yaml │ │ │ └── kustomization.yaml │ │ ├── qa │ │ │ └── kustomization.yaml │ │ └── prod │ │ │ └── kustomization.yaml │ └── contrast-agent-operator │ │ ├── base │ │ ├── default-agent-connection-secret.yaml │ │ ├── default-agent-configuration.yaml │ │ └── default-agent-connection.yaml │ │ ├── kustomization.yaml │ │ └── overlays │ │ └── demo-settings.yaml └── projects │ ├── contrast-agent-operator.yaml │ ├── definitions.yaml │ ├── argocd.yaml │ └── super-awesome-app.yaml ├── .editorconfig ├── README.md ├── LICENSE └── setup └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.sh text eol=lf 3 | -------------------------------------------------------------------------------- /src/workloads/argocd/base/argocd-namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: argocd 5 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/all/base/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: default 5 | -------------------------------------------------------------------------------- /src/workloads/argocd/overlays/argocd-rbac-cm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: argocd-rbac-cm 5 | data: 6 | policy.default: role:admin 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | 8 | [*.yaml] 9 | indent_style = space 10 | indent_size = 2 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # agent-operator-demo 2 | 3 | ## Services 4 | 5 | - ArgoCD: https://localhost:8082/applications 6 | - Netflicks (.NET 6) QA: http://localhost:8083/ 7 | - Netflicks (.NET 6) Prod: http://localhost:8084/ 8 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/all/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - base/namespace.yaml 3 | - base/netflicks-net-deployment.yaml 4 | - base/netflicks-net-injector.yaml 5 | - base/netflicks-net-service.yaml 6 | - base/petclinic-java-deployment.yaml 7 | - base/petclinic-java-injector.yaml 8 | -------------------------------------------------------------------------------- /src/workloads/argocd/overlays/argocd-server-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: argocd-server 5 | spec: 6 | ports: 7 | - name: https 8 | port: 443 9 | protocol: TCP 10 | targetPort: 8080 11 | nodePort: 30082 12 | type: NodePort 13 | -------------------------------------------------------------------------------- /src/workloads/contrast-agent-operator/base/default-agent-connection-secret.yaml: -------------------------------------------------------------------------------- 1 | # kubectl -n contrast-agent-operator \ 2 | # create secret generic default-agent-connection-secret \ 3 | # --from-literal=apiKey=TODO \ 4 | # --from-literal=serviceKey=TODO \ 5 | # --from-literal=userName=TODO 6 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/all/base/petclinic-java-injector.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: agents.contrastsecurity.com/v1beta1 2 | kind: AgentInjector 3 | metadata: 4 | name: petclinic-java-injector 5 | spec: 6 | type: java 7 | selector: 8 | labels: 9 | - name: contrast/inject 10 | value: java 11 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/qa/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namespace: super-awesome-app-qa 2 | 3 | bases: 4 | - ../all 5 | 6 | patches: 7 | - target: 8 | kind: Service 9 | name: netflicks-net 10 | patch: |- 11 | - op: replace 12 | path: /spec/ports/0/nodePort 13 | value: 30083 14 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/all/base/netflicks-net-injector.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: agents.contrastsecurity.com/v1beta1 2 | kind: AgentInjector 3 | metadata: 4 | name: netflicks-net-injector 5 | spec: 6 | type: dotnet-core 7 | selector: 8 | labels: 9 | - name: contrast/inject 10 | value: dotnet-core 11 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/prod/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namespace: super-awesome-app-prod 2 | 3 | bases: 4 | - ../all 5 | 6 | patches: 7 | - target: 8 | kind: Service 9 | name: netflicks-net 10 | patch: |- 11 | - op: replace 12 | path: /spec/ports/0/nodePort 13 | value: 30084 14 | -------------------------------------------------------------------------------- /src/workloads/argocd/overlays/argocd-cm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: argocd-cm 5 | data: 6 | url: http://localhost:8082 7 | repositories: | 8 | - type: helm 9 | url: https://kubernetes.github.io/dashboard/ 10 | name: kubernetes-dashboard 11 | users.anonymous.enabled: "true" 12 | -------------------------------------------------------------------------------- /src/workloads/contrast-agent-operator/base/default-agent-configuration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: agents.contrastsecurity.com/v1beta1 2 | kind: ClusterAgentConfiguration 3 | metadata: 4 | name: default-agent-configuration 5 | namespace: contrast-agent-operator 6 | spec: 7 | template: 8 | spec: 9 | yaml: | 10 | # Empty 11 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/all/base/netflicks-net-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: netflicks-net 5 | spec: 6 | ports: 7 | - name: http 8 | nodePort: 30083 9 | port: 80 10 | protocol: TCP 11 | targetPort: 80 12 | selector: 13 | app.kubernetes.io/name: netflicks-net 14 | type: NodePort 15 | -------------------------------------------------------------------------------- /src/workloads/contrast-agent-operator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namespace: contrast-agent-operator 2 | 3 | bases: 4 | - github.com/Contrast-Security-OSS/agent-operator/manifests/install/prod?ref=v0.9.0 5 | 6 | resources: 7 | - base/default-agent-configuration.yaml 8 | - base/default-agent-connection.yaml 9 | 10 | patchesStrategicMerge: 11 | - overlays/demo-settings.yaml 12 | -------------------------------------------------------------------------------- /src/workloads/contrast-agent-operator/overlays/demo-settings.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: contrast-agent-operator 5 | namespace: contrast-agent-operator 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: contrast-agent-operator 11 | env: 12 | - name: CONTRAST_EVENT_QUEUE_MERGE_WINDOW_SECONDS 13 | value: "1" 14 | -------------------------------------------------------------------------------- /src/projects/contrast-agent-operator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: contrast-agent-operator 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/Contrast-Security-OSS/agent-operator-demo.git 10 | targetRevision: HEAD 11 | path: src/workloads/contrast-agent-operator 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: default 15 | -------------------------------------------------------------------------------- /src/projects/definitions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: definitions 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/Contrast-Security-OSS/agent-operator-demo.git 10 | targetRevision: HEAD 11 | path: src/projects 12 | directory: 13 | recurse: true 14 | destination: 15 | server: https://kubernetes.default.svc 16 | namespace: default 17 | syncPolicy: 18 | automated: {} 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Contrast Security, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /src/projects/argocd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: argocd 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/Contrast-Security-OSS/agent-operator-demo.git 10 | targetRevision: HEAD 11 | path: src/workloads/argocd 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: default 15 | ignoreDifferences: 16 | - group: '' 17 | kind: Secret 18 | name: argocd-secret 19 | jsonPointers: 20 | - /metadata/annotations 21 | - /metadata/labels/app.kubernetes.io~1instance 22 | -------------------------------------------------------------------------------- /src/workloads/contrast-agent-operator/base/default-agent-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: agents.contrastsecurity.com/v1beta1 2 | kind: ClusterAgentConnection 3 | metadata: 4 | name: default-agent-connection 5 | namespace: contrast-agent-operator 6 | spec: 7 | template: 8 | spec: 9 | url: https://apptwo.contrastsecurity.com/Contrast 10 | apiKey: 11 | secretName: default-agent-connection-secret 12 | secretKey: apiKey 13 | serviceKey: 14 | secretName: default-agent-connection-secret 15 | secretKey: serviceKey 16 | userName: 17 | secretName: default-agent-connection-secret 18 | secretKey: userName 19 | -------------------------------------------------------------------------------- /src/workloads/argocd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namespace: argocd 2 | 3 | # Upstream kustomize is broken with this syntax: 4 | # https://github.com/kubernetes-sigs/kustomize/issues/2538 5 | # Downgrade to 3.5.5 if you need to rebuild this. e.g. reinstall Argocd during major upgrades. 6 | # https://github.com/kubernetes-sigs/kustomize/releases/tag/kustomize%2Fv3.5.5 7 | # ^ This seems fixed in at least v4.5.7. 8 | 9 | bases: 10 | - github.com/argoproj/argo-cd/manifests/cluster-install?ref=v2.4.14 11 | 12 | resources: 13 | - base/argocd-namespace.yaml 14 | 15 | patchesStrategicMerge: 16 | - overlays/argocd-cm.yaml 17 | - overlays/argocd-rbac-cm.yaml 18 | - overlays/argocd-server-service.yaml 19 | -------------------------------------------------------------------------------- /src/projects/super-awesome-app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: super-awesome-app-prod 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/Contrast-Security-OSS/agent-operator-demo.git 10 | targetRevision: HEAD 11 | path: src/workloads/super-awesome-app/prod 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: default 15 | --- 16 | apiVersion: argoproj.io/v1alpha1 17 | kind: Application 18 | metadata: 19 | name: super-awesome-app-qa 20 | namespace: argocd 21 | spec: 22 | project: default 23 | source: 24 | repoURL: https://github.com/Contrast-Security-OSS/agent-operator-demo.git 25 | targetRevision: HEAD 26 | path: src/workloads/super-awesome-app/qa 27 | destination: 28 | server: https://kubernetes.default.svc 29 | namespace: default 30 | -------------------------------------------------------------------------------- /setup/README.md: -------------------------------------------------------------------------------- 1 | # Cluster Setup 2 | 3 | ## Install K3d 4 | 5 | ```bash 6 | wget -q -O - https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash 7 | ``` 8 | 9 | ```bash 10 | % k3d --version 11 | k3d version v5.4.6 12 | k3s version v1.24.4-k3s1 (default) 13 | ``` 14 | 15 | ## Create the Cluster 16 | 17 | ```bash 18 | # Create the cluster. 19 | k3d cluster create \ 20 | contrast-agent-operator-demo \ 21 | --kubeconfig-switch-context \ 22 | --api-port 6550 \ 23 | -p "8082:30082@loadbalancer" \ 24 | -p "8083:30083@loadbalancer" \ 25 | -p "8084:30084@loadbalancer" \ 26 | --agents 3 27 | 28 | # Bootstrap ArgoCD. 29 | kubectl apply -k src/workloads/argocd 30 | 31 | # Added ArgoCD projects (to start loading everything else). 32 | kubectl apply -f src/projects 33 | 34 | # Make sure to add the required secrets. 35 | kubectl -n contrast-agent-operator \ 36 | create secret generic default-agent-connection-secret \ 37 | --from-literal=apiKey=TODO \ 38 | --from-literal=serviceKey=TODO \ 39 | --from-literal=userName=TODO 40 | ``` 41 | 42 | ## Cleanup 43 | 44 | ```bash 45 | k3d cluster delete contrast-agent-operator-demo 46 | ``` 47 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/all/base/petclinic-java-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: petclinic-java 5 | labels: 6 | app.kubernetes.io/name: petclinic-java 7 | contrast/inject: java 8 | spec: 9 | replicas: 1 10 | revisionHistoryLimit: 0 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/name: petclinic-java 14 | template: 15 | metadata: 16 | labels: 17 | app.kubernetes.io/name: petclinic-java 18 | spec: 19 | containers: 20 | - image: contrastsecuritydemo/spring-petclinic:1.5.1 21 | name: app 22 | ports: 23 | - containerPort: 8080 24 | name: http 25 | livenessProbe: 26 | httpGet: 27 | path: / 28 | port: 8080 29 | readinessProbe: 30 | httpGet: 31 | path: / 32 | port: 8080 33 | startupProbe: 34 | httpGet: 35 | path: / 36 | port: 8080 37 | failureThreshold: 30 38 | periodSeconds: 3 39 | initialDelaySeconds: 30 40 | resources: 41 | limits: 42 | cpu: '1' 43 | memory: 1024M 44 | -------------------------------------------------------------------------------- /src/workloads/super-awesome-app/all/base/netflicks-net-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: netflicks-net 5 | labels: 6 | app.kubernetes.io/name: netflicks-net 7 | contrast/inject: dotnet-core 8 | spec: 9 | replicas: 1 10 | revisionHistoryLimit: 0 11 | selector: 12 | matchLabels: 13 | app.kubernetes.io/name: netflicks-net 14 | template: 15 | metadata: 16 | labels: 17 | app.kubernetes.io/name: netflicks-net 18 | spec: 19 | containers: 20 | - image: contrastsecuritydemo/netflicks:1.0 21 | name: app 22 | ports: 23 | - containerPort: 80 24 | name: http 25 | env: 26 | - name: ConnectionStrings__DotNetFlicksConnection 27 | value: "Server=tcp:localhost,1433;Initial Catalog=DotNetFlicksDb;Persist Security Info=False;User ID=sa;Password=reallyStrongPwd123;MultipleActiveResultSets=False;" 28 | livenessProbe: 29 | httpGet: 30 | path: / 31 | port: 80 32 | readinessProbe: 33 | httpGet: 34 | path: / 35 | port: 80 36 | startupProbe: 37 | httpGet: 38 | path: / 39 | port: 80 40 | initialDelaySeconds: 5 41 | resources: 42 | limits: 43 | cpu: '1' 44 | memory: 1024M 45 | - name: netflicks-db 46 | image: mcr.microsoft.com/mssql/server:2019-latest 47 | ports: 48 | - containerPort: 1433 49 | env: 50 | - name: ACCEPT_EULA 51 | value: "Y" 52 | - name: SA_PASSWORD 53 | value: "reallyStrongPwd123" 54 | resources: 55 | limits: 56 | cpu: '1' 57 | memory: 2048M 58 | --------------------------------------------------------------------------------