github.com/inspektor-gadget/inspektor-gadget@v0.28.1/docs/builtin-gadgets/advise/seccomp-profile.md (about)

     1  ---
     2  title: 'Using advise seccomp-profile'
     3  weight: 20
     4  description: >
     5    Generate seccomp profiles based on recorded syscalls activity.
     6  ---
     7  
     8  The seccomp profile advisor gadget records syscalls that are issued in a
     9  specified pod, and then uses this information to generate the corresponding
    10  seccomp profile. It can integrate with the [Kubernetes Security Profile
    11  Operator](https://github.com/kubernetes-sigs/security-profiles-operator),
    12  directly generating the necessary `seccompprofile` resource.
    13  
    14  ### On Kubernetes
    15  
    16  #### Basic usage
    17  
    18  For this demo, we will use a sample Python workload that uses uwsgi, flask
    19  and nginx. The deployment is split in two pieces, the `basic.yaml` file
    20  that has the infrastructure, and the `unconfined.yaml` file that has the
    21  pod definition, with no seccomp profile applied.
    22  
    23  ```bash
    24  $ kubectl apply -f docs/examples/seccomp/basic.yaml
    25  namespace/seccomp-demo created
    26  configmap/app-script created
    27  service/hello-python-service created
    28  $ kubectl apply -f docs/examples/seccomp/unconfined.yaml
    29  pod/hello-python created
    30  ```
    31  
    32  It is now time to monitor system calls made by our pod:
    33  
    34  ```bash
    35  $ kubectl gadget advise seccomp-profile start -n seccomp-demo -p hello-python
    36  jMzhur2dQjZJxDCI
    37  ```
    38  
    39  The string we receive is the identifier that we will use to refer to the
    40  running operation when we want to stop it.
    41  
    42  While the advisor is running, we need to interact with the workload, to get it to generate
    43  system calls. In our example, it's a simple webservice, and we can interact
    44  with it by forwarding the service port and then querying the service
    45  
    46  ```bash
    47  $ kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000 &
    48  [1] 23574
    49  Forwarding from 127.0.0.1:8080 -> 80
    50  Forwarding from [::1]:8080 -> 80
    51  
    52  $ curl localhost:8080
    53  Handling connection for 8080
    54  Hello World!
    55  
    56  $ kill %1
    57  [1]+  Terminated              kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000
    58  ```
    59  
    60  Once we have captured the syscalls, we can ask the gadget to generate the
    61  corresponding profile, by stopping the operation with the identifier we had
    62  received before.
    63  
    64  ```bash
    65  $ kubectl gadget advise seccomp-profile stop jMzhur2dQjZJxDCI
    66  {
    67    "defaultAction": "SCMP_ACT_ERRNO",
    68    "architectures": [
    69      "SCMP_ARCH_X86_64",
    70      "SCMP_ARCH_X86",
    71      "SCMP_ARCH_X32"
    72    ],
    73    "syscalls": [
    74      {
    75        "names": [
    76          "accept4",
    77          "close",
    78          "connect",
    79          "epoll_ctl",
    80          "epoll_wait",
    81          "fstat",
    82          "getsockname",
    83          "getsockopt",
    84          "ioctl",
    85          "poll",
    86          "read",
    87          "recvfrom",
    88          "setsockopt",
    89          "socket",
    90          "stat",
    91          "wait4",
    92          "write",
    93          "writev"
    94        ],
    95        "action": "SCMP_ACT_ALLOW"
    96      }
    97    ]
    98  }
    99  ```
   100  
   101  #### Capturing all syscalls needed to bring up the pod
   102  
   103  That sample policy contains only the syscalls executed for that one single
   104  request that we made. If we want to apply a policy to our pod, we need to
   105  also include all the calls needed to bring the pod up.  To do that, we need
   106  to start the trace before the pod is up, then bring up the pod and generate
   107  traffic.
   108  
   109  We can delete the current pod, so that we can start a fresh new trace.
   110  
   111  ```bash
   112  $ kubectl delete -f docs/examples/seccomp/unconfined.yaml
   113  pod "hello-python" deleted
   114  ```
   115  
   116  Now we can create a new trace, and then create the pod again.
   117  
   118  ```bash
   119  $ kubectl gadget advise seccomp-profile start -n seccomp-demo -p hello-python
   120  TAyR9BXes6GU04rG
   121  $ kubectl apply -f docs/examples/seccomp/unconfined.yaml
   122  pod/hello-python created
   123  ```
   124  
   125  Once the pod is up, we can once again generate some traffic, like before.
   126  
   127  ```bash
   128  $ kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000 &
   129  [1] 28318
   130  Forwarding from 127.0.0.1:8080 -> 80
   131  Forwarding from [::1]:8080 -> 80
   132  
   133  $ curl localhost:8080
   134  Handling connection for 8080
   135  Hello World!
   136  
   137  $ kill %1
   138  [1]+  Terminated              kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000
   139  ```
   140  
   141  And now generate the policy again:
   142  
   143  ```bash
   144  $ kubectl gadget advise seccomp-profile stop TAyR9BXes6GU04rG
   145  {
   146  	...
   147  }
   148  ```
   149  
   150  This time, the output field will contain a lot more syscalls, as a lot of
   151  operations need to take place to bring up the pod.
   152  
   153  #### Integration with Kubernetes Security Profiles Operator
   154  
   155  We can use the output stored in the trace to create the seccomp policy for our
   156  pod. But instead of copying it manually, we can also use the integration with
   157  the [Kubernetes Security Profiles Operator
   158  (SPO)](https://github.com/kubernetes-sigs/security-profiles-operator). Notice
   159  the seccomp gadget uses the seccomp profile API `v1beta1`, so at least SPO
   160  v0.4.0 is required. Check the [SPO
   161  documentation](https://github.com/kubernetes-sigs/security-profiles-operator/blob/main/installation-usage.md#install-operator)
   162  for details about installation. Once the SPO is installed, the seccomp gadget
   163  can generate `seccompprofile` resources that can be used directly by our pods.
   164  
   165  We need to use the `--output-mode` (or simply `-m`) option to create the
   166  `SeccompProfile` resource instead of printing the policy in the terminal
   167  (default behaviour). Consider that using the option `--profile-prefix`,
   168  we can specify the namespace and the prefix-name of the resource:
   169  `namespace/prefix-name`. Notice the namespace is not mandatory.
   170  If the option `--profile-prefix` is not used, the resource will be
   171  automatically named using the pod name, and it will be created in the
   172  trace's namespace (`gadget` if kubectl-gadget CLI was used).
   173  
   174  ```bash
   175  # Delete the pod.
   176  $ kubectl delete -f docs/examples/seccomp/unconfined.yaml
   177  pod "hello-python" deleted
   178  
   179  # Create the pod and start a new trace again
   180  $ kubectl gadget advise seccomp-profile start -m seccomp-profile -n seccomp-demo -p hello-python
   181  TAyR9BXes6GU04rG
   182  $ kubectl apply -f docs/examples/seccomp/unconfined.yaml
   183  pod/hello-python created
   184  
   185  # Generate traffic once again
   186  $ kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000 &
   187  [1] 33679
   188  Forwarding from 127.0.0.1:8080 -> 80
   189  Forwarding from [::1]:8080 -> 80
   190  $ curl localhost:8080
   191  Handling connection for 8080
   192  Hello World!
   193  $ kill %1
   194  [1]+  Terminated              kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000
   195  
   196  # Now stop the gadget to generate the seccomp profile.
   197  $ kubectl gadget advise seccomp-profile stop TAyR9BXes6GU04rG
   198  $ kubectl get seccompprofile -n gadget
   199  NAME            STATUS      AGE
   200  hello-python    Installed   9s
   201  ```
   202  
   203  This profile can now be used as the seccomp profile for our pod. To do
   204  that, we need to edit the configuration and replace the `Unconfined`
   205  setting in our profile type, set it to `Localhost`, and add a
   206  `localhostProfile` entry that points to the profile we just generated.
   207  
   208  ```yaml
   209  spec:
   210    securityContext:
   211      seccompProfile:
   212        type: Localhost
   213        localhostProfile: operator/gadget/hello-python.json
   214  ```
   215  
   216  We have this change already applied in the `confined.yaml` file. To apply
   217  this change, we need to delete the current pod and create a new one with
   218  the new configuration:
   219  
   220  ```bash
   221  $ kubectl delete -f docs/examples/seccomp/unconfined.yaml
   222  pod "hello-python" deleted
   223  $ kubectl apply -f docs/examples/seccomp/confined.yaml
   224  pod/hello-python created
   225  ```
   226  
   227  Our workload is now running with the seccomp profile. We can verify that
   228  it's running correctly by querying it once again like before:
   229  
   230  ```bash
   231  $ kubectl port-forward service/hello-python-service -n seccomp-demo 8080:6000 &
   232  [1] 41643
   233  $ Forwarding from 127.0.0.1:8080 -> 80
   234  Forwarding from [::1]:8080 -> 80
   235  
   236  $ curl localhost:8080
   237  Handling connection for 8080
   238  Hello World!
   239  ```
   240  
   241  The request is allowed (as expected), but processes that require additional
   242  syscalls will be blocked. For example, if we try to execute a shell in our
   243  pod:
   244  
   245  ```bash
   246  $ kubectl exec -it -n seccomp-demo hello-python -- /bin/bash
   247  bash: initialize_job_control: getpgrp failed: Success
   248  command terminated with exit code 1
   249  ```
   250  
   251  We see that the seccomp profile is preventing this execution, and it will
   252  prevent any other execution that requires syscalls that were not part of
   253  the captured calls.
   254  
   255  #### Cleanup
   256  
   257  Once we're done with the demo, we can delete all the resources that we've
   258  used by deleting the `seccomp-demo` namespace:
   259  
   260  ```bash
   261  $ kubectl delete ns seccomp-demo
   262  namespace "seccomp-demo" deleted
   263  ```
   264  
   265  ### With `ig`
   266  
   267  TODO!
   268  
   269  ### Troubleshooting
   270  
   271  1. If the annotations don't do anything, check that the node field is set
   272     correctly. You can also look at the `Status` field of the `Trace` for
   273     other possible errors.
   274  
   275  2. If the confined pod fails to start with this error:
   276     `cannot load seccomp profile "/var/lib/kubelet/seccomp/operator/seccomp-demo/hello-profile.json"`,
   277     check that the operator is correctly installed and all pods involved are
   278     running.