Code Monkey home page Code Monkey logo

audit2rbac's Introduction

audit2rbac

Overview

audit2rbac takes a Kubernetes audit log and username as input, and generates RBAC role and binding objects that cover all the API requests made by that user.

Demo Video

User Instructions

  1. Obtain a Kubernetes audit log containing all the API requests you expect your user to perform:

    • The log must be in JSON format. This requires running an API server with an --audit-policy-file defined. See documentation for more details.
    • audit.k8s.io/v1, audit.k8s.io/v1beta1 and audit.k8s.io/v1alpha1 events are supported.
    • The Metadata log level works best to minimize log size.
    • To exercise all API calls, it is sometimes necessary to grant broad access to a user or application to avoid short-circuiting code paths on failed API requests. This should be done cautiously, ideally in a development environment.
    • A sample audit policy and a sample audit log containing requests from alice, bob, and the service account ns1:sa1 is available.
  2. Identify a specific user you want to scan for audit events for and generate roles and role bindings for:

    • Specify a normal user with --user <username>
    • Specify a service account with --serviceaccount <namespace>:<name>
  3. Run audit2rbac, capturing the output:

    audit2rbac -f https://git.io/v51iG --user alice             > alice-roles.yaml
    audit2rbac -f https://git.io/v51iG --user bob               > bob-roles.yaml
    audit2rbac -f https://git.io/v51iG --serviceaccount ns1:sa1 > sa1-roles.yaml
  4. Inspect the output to verify the generated roles/bindings:

    more alice-roles.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      labels:
        audit2rbac.liggitt.net/generated: "true"
        audit2rbac.liggitt.net/user: alice
      name: audit2rbac:alice
      namespace: ns1
    rules:
    - apiGroups:
      - ""
      resources:
      - configmaps
      - pods
      - secrets
      verbs:
      - get
      - list
      - watch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      labels:
        audit2rbac.liggitt.net/generated: "true"
        audit2rbac.liggitt.net/user: alice
      name: audit2rbac:alice
      namespace: ns1
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: audit2rbac:alice
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: alice
  5. Load the generated roles/bindings:

    kubectl create -f roles.yaml
    
    role "audit2rbac:alice" created
    rolebinding "audit2rbac:alice" created

Developer Instructions

Requirements:

  • Go 1.17+

To build and install from source:

go get -d github.com/liggitt/audit2rbac
cd $GOPATH/src/github.com/liggitt/audit2rbac
git fetch --tags
make install-deps
make install

audit2rbac's People

Contributors

liggitt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

audit2rbac's Issues

Allow specifying a file/folder to output generated objects to

Rather than writing output to stdout, allow specifying an output file

This is a prereq for generating intermediate results when processing a large or continuous audit stream

Could either generate everything into a single file, or generate a file per type (clusterroles, roles, clusterrolebindings, rolebindings)... not sure which is better.

When generating, would generate to a tmp file, then do an atomic move into place, so an apply loop operating on the file would never get a partially written file.

invalid Roles are outputted

the tool is great but has a bug. it outputs roles and clusterroles with resourceNames even when it includes the create verb which is not possible in K8s.
is this something that can be fixed in the project?
currently i am manually removing the resource names field from those places but it would be much better if the tool did this itself

Documentation error ?

Hi Jordan,

First, thank's for the tool.
I'm crrently testing it and failed, first, activating auditing on a cluster initiated using kubeadm.

Apparently the proper option is :
--feature-gates=AdvancedAuditing=true
instead of
--feature-gates=AdvancedAudit=true

Your documentation mention the later.

This other issue helped me pointing out the problem :
kubernetes/kubernetes@3920b0e

Thank's again and best regards !
Thierry

Too wide permissions given

First of all, thanks for the tool, it is really helpful.

We are working on RBAC rules that allow our users to generate kubernetes configs out of long living API tokens using a script. This script issues the following API request to determine a list of secrets in a given namespace:

{
  "kind": "Event",
  "apiVersion": "audit.k8s.io/v1",
  "level": "Metadata",
  "auditID": "08c32d69-9410-4475-8d69-7e57ccd6f9a0",
  "stage": "RequestReceived",
  "requestURI": "/api/v1/namespaces/infra/secrets?limit=500",
  "verb": "list",
  "user": {
    "username": "redacted",
    "groups": [
      "aad:dfe1dbdbredacted",
      "aad:8d8309beredacted",
      "system:authenticated"
    ]
  },
  "sourceIPs": [
    "192.168.0.1"
  ],
  "userAgent": "kubectl/v1.27.4 (linux/amd64) kubernetes/fa3d799",
  "objectRef": {
    "resource": "secrets",
    "namespace": "infra",
    "apiVersion": "v1"
  },
  "requestReceivedTimestamp": "2023-10-04T09:50:02.575962Z",
  "stageTimestamp": "2023-10-04T09:50:02.575962Z"
}

But for this audit2rbac generates a role that allows more verbs (including get) for the secrets:

# echo '{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"08c32d69-9410-4475-8d69-7e57ccd6f9a0","stage":"RequestReceived","requestURI":"/api/v1/namespaces/infra/secrets?limit=500","verb":"list","user":{"username":"redacted","groups":["aad:dfe1dbdbredacted","aad:8d8309beredacted","system:authenticated"]},"sourceIPs":["192.168.0.1"],"userAgent":"kubectl/v1.27.4 (linux/amd64) kubernetes/fa3d799","objectRef":{"resource":"secrets","namespace":"infra","apiVersion":"v1"},"requestReceivedTimestamp":"2023-10-04T09:50:02.575962Z","stageTimestamp":"2023-10-04T09:50:02.575962Z"}'| audit2rbac --filename - --user redacted
Opening audit source...
Loading events...
Evaluating API calls...
Generating roles...
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  annotations:
    audit2rbac.liggitt.net/version: v0.10.0
  labels:
    audit2rbac.liggitt.net/generated: "true"
    audit2rbac.liggitt.net/user: redacted
  name: audit2rbac:redacted
  namespace: infra
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  annotations:
    audit2rbac.liggitt.net/version: v0.10.0
  labels:
    audit2rbac.liggitt.net/generated: "true"
    audit2rbac.liggitt.net/user: redacted
  name: audit2rbac:redacted
  namespace: infra
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: audit2rbac:redacted
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: redacted
Complete!

Are these verbs really required for this API call? Can you please explain what is the reason behind?

Problem building from source: malformed module path "io/fs": missing dot in first path element

When I try to build from source according to the documentation listed in the README.md, I get the following error:

~ /go/src/github.com/liggitt/audit2rbac : make install-deps                                                                                                                           
go mod vendor
...
github.com/liggitt/audit2rbac/cmd/audit2rbac imports
    k8s.io/apiserver/pkg/authentication/serviceaccount imports
    k8s.io/client-go/kubernetes/typed/core/v1 imports
    k8s.io/client-go/rest imports
    k8s.io/client-go/plugin/pkg/client/auth/exec imports
    io/fs: malformed module path "io/fs": missing dot in first path element
make: *** [Makefile:9: install-deps] Error 1   

I found someone talking about this issue here (https://gist.github.com/Integralist/2ad28a16f303b13dd58e41b3831961e3), however I don't understand Golang's packaging system well enough to troubleshoot the issue on my own. Any suggestions?

glide install hangs on k8s.io/kubernetes

Doesn't seem to recover and hangs here for hours.

make install-deps glide install -v [INFO] Downloading dependencies. Please wait... [INFO] --> Found desired version locally github.com/davecgh/go-spew 782f4967f2dc4564575ca782fe2d04090b5faca8! [INFO] --> Found desired version locally github.com/emicklei/go-restful ff4f55a206334ef123e4f79bbf348980da81ca46! [INFO] --> Found desired version locally github.com/ghodss/yaml 73d445a93680fa1a78ae23a5839bad48f32ba1ee! [INFO] --> Found desired version locally github.com/go-openapi/jsonpointer 46af16f9f7b149af66e5d1bd010e3574dc06de98! [INFO] --> Found desired version locally github.com/go-openapi/jsonreference 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272! [INFO] --> Found desired version locally github.com/go-openapi/spec 6aced65f8501fe1217321abf0749d354824ba2ff! [INFO] --> Found desired version locally github.com/go-openapi/swag 1d0bd113de87027671077d3c71eb3ac5d7dbba72! [INFO] --> Found desired version locally github.com/gogo/protobuf c0656edd0d9eab7c66d1eb0c568f9039345796f7! [INFO] --> Found desired version locally github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed! [INFO] --> Found desired version locally github.com/google/btree 7d79101e329e5a3adf994758c578dab82b90c017! [INFO] --> Found desired version locally github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c! [INFO] --> Found desired version locally github.com/gregjones/httpcache 787624de3eb7bd915c329cba748687a3b22666a6! [INFO] --> Found desired version locally github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4! [INFO] --> Found desired version locally github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75! [INFO] --> Found desired version locally github.com/json-iterator/go 36b14963da70d11297d313183d7e6388c8510e1e! [INFO] --> Found desired version locally github.com/juju/ratelimit 5b9ff866471762aa2ab2dced63c9fb6f53921342! [INFO] --> Found desired version locally github.com/mailru/easyjson d5b7844b561a7bc640052f1b935f7b800330d7e0! [INFO] --> Found desired version locally github.com/peterbourgon/diskv 5f041e8faa004a95c88a202771f4cc3e991971e6! [INFO] --> Found desired version locally github.com/PuerkitoBio/purell 8a290539e2e8629dbc4e6bad948158f790ec31f4! [INFO] --> Found desired version locally github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e! [INFO] --> Found desired version locally github.com/spf13/cobra f62e98d28ab7ad31d707ba837a966378465c7b57! [INFO] --> Found desired version locally github.com/spf13/pflag 9ff6c6923cfffbcd502984b8e0c80539a94968b7! [INFO] --> Found desired version locally golang.org/x/net 1c05540f6879653db88113bc4a2b70aec4bd491f! [INFO] --> Found desired version locally golang.org/x/text b19bf474d317b857955b12035d2c5acb57ce8b01! [INFO] --> Found desired version locally gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4! [INFO] --> Found desired version locally gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77! [INFO] --> Found desired version locally k8s.io/api fe29995db37613b9c5b2a647544cf627bfa8d299! [INFO] --> Found desired version locally k8s.io/apimachinery 9d38e20d609d27e00d4ec18f7b9db67105a2bde0! [INFO] --> Found desired version locally k8s.io/apiserver f9b476d61dbdf6474e3d42cc5e854d0d8b7f759e! [INFO] --> Found desired version locally k8s.io/client-go afb4606c45bae77c4dc2c15291d4d7d6d792196c! [INFO] --> Found desired version locally k8s.io/kube-openapi 868f2f29720b192240e18284659231b440f9cda5! [INFO] --> Fetching k8s.io/kubernetes

audit2rbac as a kubectl plugin

Thank you @liggitt for this extremely useful tool.

Are you open to making this tool available and usable as a kubectl plugin?

If so, I would not mind working on PR for this.

Support for Google Kubernetes Engine (GKE)

Google's managed Kubernetes service redirects the Kubernetes Audit Log to their Cloud Audit Logging/Stackdriver Logging services. These logs can be queried using the gcloud command line tools, eg:

gcloud logging read --freshness=1h --format=json 'logName="projects/MY_PROJECT_NAME/logs/cloudaudit.googleapis.com%2Factivity" severity=ERROR'

This produces output formatted like this:

[
  {
    "insertId": "230ba8alnweli",
    "labels": {
      "cluster_version": "1.10.6-gke.2"
    },
    "logName": "projects/test-project/logs/cloudaudit.googleapis.com%2Factivity",
    "operation": {
      "id": "ae820cad-230q-ae80-8ca0-ce0af238adwd",
      "producer": "k8s.io"
    },
    "protoPayload": {
      "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
      "authenticationInfo": {
        "principalEmail": "system:serviceaccount:test-ns:test-sa"
      },
      "authorizationInfo": [
        {
          "permission": "com.coreos.database.etcd.v1beta2.etcdbackups.create",
          "resource": "etcd.database.coreos.com/v1beta2/namespaces/test-ns/etcdbackups"
        }
      ],
      "methodName": "com.coreos.database.etcd.v1beta2.etcdbackups.create",
      "requestMetadata": {
        "callerIp": "78.123.102.30"
      },
      "resourceName": "etcd.database.coreos.com/v1beta2/namespaces/test-ns/etcdbackups",
      "serviceName": "k8s.io",
      "status": {
        "code": 7,
        "message": "etcdbackups.etcd.database.coreos.com is forbidden: User \"system:serviceaccount:test-ns:test-sa\" cannot create etcdbackups.etcd.database.coreos.com in the namespace \"test-ns\": Unknown user \"system:serviceaccount:test-ns:test-sa\""
      }
    },
    "receiveTimestamp": "2018-09-10T11:18:00.109312987Z",
    "resource": {
      "labels": {
        "cluster_name": "test-cluster",
        "location": "us-central1",
        "project_id": "test-project"
      },
      "type": "k8s_cluster"
    },
    "severity": "ERROR",
    "timestamp": "2018-09-10T11:18:00.109312Z"
  }
]

Would it be reasonable to try to support this format in audit2rbac?

(I am relatively new to Kubernetes/GKE so I could be mistaken about how GKE's audit logging works, but I think the above description is accurate.)

Unable to use with KOPS prior to 1.8

Since an --audit-policy-file parameter must be defined to make audit2rbac works. Cluster built with KOPS < 1.8 can't use the tool to generates RBAC role and binding objects.

"Audit Policy File" had been merged only for KOPS 1.8:
kubernetes/kops#3692

Or, is this ok to use KOPS 1.8 with Kubernetes 1.6 ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.