├── .gitignore ├── .goreleaser.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── Makefile ├── README.md ├── cmd └── pid2pod-demo │ └── main.go ├── pid2pod.go └── vendor └── github.com ├── mitchellh └── go-ps │ ├── .gitignore │ ├── .travis.yml │ ├── LICENSE.md │ ├── README.md │ ├── Vagrantfile │ ├── process.go │ ├── process_darwin.go │ ├── process_darwin_test.go │ ├── process_freebsd.go │ ├── process_linux.go │ ├── process_solaris.go │ ├── process_test.go │ ├── process_unix.go │ ├── process_unix_test.go │ └── process_windows.go └── pkg └── errors ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── appveyor.yml ├── bench_test.go ├── errors.go ├── errors_test.go ├── example_test.go ├── format_test.go ├── stack.go └── stack_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | # Configuration for https://goreleaser.com/ 2 | project_name: pid2pod 3 | 4 | builds: 5 | - binary: pid2pod-demo 6 | main: ./cmd/pid2pod-demo/main.go 7 | goos: 8 | - linux 9 | goarch: 10 | - amd64 11 | env: 12 | - CGO_ENABLED=0 13 | 14 | dockers: 15 | - image: gcr.io/heptio-images/pid2pod-demo 16 | binary: pid2pod-demo 17 | dockerfile: Dockerfile 18 | 19 | snapshot: 20 | name_template: "git-{{.Commit}}" 21 | 22 | archive: 23 | format: binary 24 | 25 | release: 26 | github: 27 | owner: heptiolabs 28 | name: pid2pod 29 | draft: true 30 | prerelease: true 31 | name_template: "v{{.Version}}" 32 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Code of Conduct 2 | 3 | ## Contributor Code of Conduct 4 | 5 | As contributors and maintainers of this project, and in the interest of fostering 6 | an open and welcoming community, we pledge to respect all people who contribute 7 | through reporting issues, posting feature requests, updating documentation, 8 | submitting pull requests or patches, and other activities. 9 | 10 | We are committed to making participation in this project a harassment-free experience for 11 | everyone, regardless of level of experience, gender, gender identity and expression, 12 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, 13 | religion, or nationality. 14 | 15 | Examples of unacceptable behavior by participants include: 16 | 17 | * The use of sexualized language or imagery 18 | * Personal attacks 19 | * Trolling or insulting/derogatory comments 20 | * Public or private harassment 21 | * Publishing other's private information, such as physical or electronic addresses, 22 | without explicit permission 23 | * Other unethical or unprofessional conduct. 24 | 25 | Project maintainers have the right and responsibility to remove, edit, or reject 26 | comments, commits, code, wiki edits, issues, and other contributions that are not 27 | aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers 28 | commit themselves to fairly and consistently applying these principles to every aspect 29 | of managing this project. Project maintainers who do not follow or enforce the Code of 30 | Conduct may be permanently removed from the project team. 31 | 32 | This code of conduct applies both within project spaces and in public spaces 33 | when an individual is representing the project or its community. 34 | 35 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer(s). 36 | 37 | This Code of Conduct is adapted from the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md) and [Contributor Covenant](http://contributor-covenant.org/version/1/2/0/), version 1.2.0. 38 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## DCO Sign off 2 | 3 | All authors to the project retain copyright to their work. However, to ensure 4 | that they are only submitting work that they have rights to, we are requiring 5 | everyone to acknowldge this by signing their work. 6 | 7 | Any copyright notices in this repos should specify the authors as "the contributors". 8 | 9 | To sign your work, just add a line like this at the end of your commit message: 10 | 11 | ``` 12 | Signed-off-by: Joe Beda 13 | ``` 14 | 15 | This can easily be done with the `--signoff` option to `git commit`. 16 | 17 | By doing this you state that you can certify the following (from https://developercertificate.org/): 18 | 19 | ``` 20 | Developer Certificate of Origin 21 | Version 1.1 22 | 23 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 24 | 1 Letterman Drive 25 | Suite D4700 26 | San Francisco, CA, 94129 27 | 28 | Everyone is permitted to copy and distribute verbatim copies of this 29 | license document, but changing it is not allowed. 30 | 31 | 32 | Developer's Certificate of Origin 1.1 33 | 34 | By making a contribution to this project, I certify that: 35 | 36 | (a) The contribution was created in whole or in part by me and I 37 | have the right to submit it under the open source license 38 | indicated in the file; or 39 | 40 | (b) The contribution is based upon previous work that, to the best 41 | of my knowledge, is covered under an appropriate open source 42 | license and I have the right under that license to submit that 43 | work with modifications, whether created in whole or in part 44 | by me, under the same open source license (unless I am 45 | permitted to submit under a different license), as indicated 46 | in the file; or 47 | 48 | (c) The contribution was provided directly to me by some other 49 | person who certified (a), (b) or (c) and I have not modified 50 | it. 51 | 52 | (d) I understand and agree that this project and the contribution 53 | are public and that a record of the contribution (including all 54 | personal information I submit with it, including my sign-off) is 55 | maintained indefinitely and may be redistributed consistent with 56 | this project or the open source license(s) involved. 57 | ``` -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 by the contributors. 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 | 15 | 16 | FROM scratch 17 | COPY pid2pod-demo / 18 | ENTRYPOINT ["/pid2pod-demo"] 19 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "master" 6 | name = "github.com/mitchellh/go-ps" 7 | packages = ["."] 8 | revision = "4fdf99ab29366514c69ccccddab5dc58b8d84062" 9 | 10 | [[projects]] 11 | name = "github.com/pkg/errors" 12 | packages = ["."] 13 | revision = "645ef00459ed84a119197bfb8d8205042c6df63d" 14 | version = "v0.8.0" 15 | 16 | [solve-meta] 17 | analyzer-name = "dep" 18 | analyzer-version = 1 19 | inputs-digest = "45612762c135df25450b499fdc0a4b36cef53fc84d9a085300e88abf4ec1954b" 20 | solver-name = "gps-cdcl" 21 | solver-version = 1 22 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | 22 | 23 | [[constraint]] 24 | branch = "master" 25 | name = "github.com/mitchellh/go-ps" 26 | 27 | [[constraint]] 28 | name = "github.com/pkg/errors" 29 | version = "0.8.0" 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: build 2 | 3 | GORELEASER := $(shell command -v goreleaser 2> /dev/null) 4 | 5 | ifndef GORELEASER 6 | $(error "goreleaser not found (`brew install goreleaser/tap/goreleaser` to fix)") 7 | endif 8 | 9 | .PHONY: build release test format 10 | 11 | build: 12 | $(GORELEASER) --rm-dist --snapshot 13 | 14 | release: 15 | $(GORELEASER) --rm-dist 16 | 17 | test: 18 | go test -v ./... 19 | 20 | format: 21 | test -z "$$(find . -path ./vendor -prune -type f -o -name '*.go' -exec gofmt -d {} + | tee /dev/stderr)" || \ 22 | test -z "$$(find . -path ./vendor -prune -type f -o -name '*.go' -exec gofmt -w {} + | tee /dev/stderr)" 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pid2pod 2 | 3 | This is a small demo/experiment that shows how Linux process IDs (PIDs) can be mapped to Kubernetes pod metadata. 4 | 5 | It works by looking up the target process's [cgroup] metadata in `/proc/$PID/cgroup`. 6 | This metadata contains the names of each cgroup assigned to the process. 7 | In the case of Docker containers created using the `docker` CLI or created by the kubelet, these cgroup names contain the Docker container ID. 8 | We can map this container ID to a Kubernetes pod by doing a lookup against the local [kubelet API][kubelet-api]. 9 | 10 | Thanks to the [SPIRE] implementation of [SPIFFE], which inspired this method ([see `k8s.go`][spiffe-impl]). 11 | 12 | ## Example Use Cases 13 | 14 | - You want to enrich [audit][go-audit] or other host-level events with pod-level metadata. 15 | 16 | - You want to control access to a UNIX domain socket based on [the calling pod][uds-pid-lookup]. 17 | 18 | ## Caveats 19 | 20 | - Not well tested. 21 | Please use this as an example but don't run this in production. 22 | 23 | - Only works for the Docker runtime. 24 | Other container runtimes may use a different scheme for cgroup names or may not even have workload PIDs visible from the host. 25 | 26 | - Assumes the kubelet read-only API (`--read-only-port`) is running on `http://localhost:10255/`. 27 | We could add token/certificate authentication to move past this assumption. 28 | 29 | - Has some inherent race conditions since a lookup from PID to pod metadata takes some time. 30 | The PID may correspond to a different process by the time the data is used. 31 | 32 | This may be avoided in some scenarios. 33 | For example, if you have a server holding an open UNIX domain socket you know the client has had the same PID for the whole connection. 34 | 35 | ## Usage 36 | 37 | The demo lists all processes on the system that it can map back to a pod. 38 | It must be run in privileged mode, in the host PID namespace, and in the host network namespace. 39 | 40 | ```console 41 | $ docker run --rm --privileged --pid=host --net=host pid2pod:latest 42 | PID 4549 (kube-proxy): &pid2pod.ID{Namespace:"kube-system", PodName:"kube-proxy-mdnzr", PodUID:"6344523c-44b7-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"controller-revision-hash":"1193416634", "k8s-app":"kube-proxy", "pod-template-generation":"1"}, ContainerID:"7d6ca8ec4775491b941aeb9d55fe52fe14236575c26b395f36d0afa8717bdaae", ContainerName:"kube-proxy"} 43 | PID 4992 (dashboard): &pid2pod.ID{Namespace:"kube-system", PodName:"kubernetes-dashboard-5498ccf677-xk55s", PodUID:"63fe5f9d-44b7-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"addonmanager.kubernetes.io/mode":"Reconcile", "app":"kubernetes-dashboard", "pod-template-hash":"1054779233", "version":"v1.8.1"}, ContainerID:"3d23b4ffce2f10bbcc10ffee5acc5bdb2446e48c9253bb51405d65ece5bf0dd2", ContainerName:"kubernetes-dashboard"} 44 | PID 5079 (kube-dns): &pid2pod.ID{Namespace:"kube-system", PodName:"kube-dns-86f4d74b45-qfs6f", PodUID:"634ab7a3-44b7-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"k8s-app":"kube-dns", "pod-template-hash":"4290830601"}, ContainerID:"8ae06d9c2b923cad2a3fd8f1c5ebaad18483d6af369f968209cc940e7f501b1a", ContainerName:"kubedns"} 45 | PID 5173 (storage-provisi): &pid2pod.ID{Namespace:"kube-system", PodName:"storage-provisioner", PodUID:"640b24b0-44b7-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"addonmanager.kubernetes.io/mode":"Reconcile", "integration-test":"storage-provisioner"}, ContainerID:"f22bff5ee043e33d952df17f9cf6d79d8b8de3b82d565566b0bef49d2a4fa809", ContainerName:"storage-provisioner"} 46 | PID 5291 (dnsmasq-nanny): &pid2pod.ID{Namespace:"kube-system", PodName:"kube-dns-86f4d74b45-qfs6f", PodUID:"634ab7a3-44b7-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"k8s-app":"kube-dns", "pod-template-hash":"4290830601"}, ContainerID:"07567b209503648459d7e5bd5ef1e943355dc479ca68c629a30cc139810a95ae", ContainerName:"dnsmasq"} 47 | PID 5339 (dnsmasq): &pid2pod.ID{Namespace:"kube-system", PodName:"kube-dns-86f4d74b45-qfs6f", PodUID:"634ab7a3-44b7-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"k8s-app":"kube-dns", "pod-template-hash":"4290830601"}, ContainerID:"07567b209503648459d7e5bd5ef1e943355dc479ca68c629a30cc139810a95ae", ContainerName:"dnsmasq"} 48 | PID 5378 (sidecar): &pid2pod.ID{Namespace:"kube-system", PodName:"kube-dns-86f4d74b45-qfs6f", PodUID:"634ab7a3-44b7-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"k8s-app":"kube-dns", "pod-template-hash":"4290830601"}, ContainerID:"fa1685e9e27b95556313641bd6b4e7f3db7893a8dcb6d85f5cc369d895be17db", ContainerName:"sidecar"} 49 | PID 16962 (sh): &pid2pod.ID{Namespace:"default", PodName:"testcli-5b8d779dfd-vpwkw", PodUID:"a8c810f7-44d3-11e8-b7fb-b2d1d7d0d428", PodLabels:map[string]string{"pod-template-hash":"1648335898", "run":"testcli"}, ContainerID:"8fe33943cbef5cdc741b265cad4c061e6232ec6187b9e00e2c2e800df7fce4aa", ContainerName:"testcli"} 50 | ``` 51 | 52 | [SPIFFE]: https://spiffe.io/ 53 | [SPIRE]: https://github.com/spiffe/spire 54 | [cgroup]: https://en.wikipedia.org/wiki/Cgroups 55 | [kubelet-api]: https://stackoverflow.com/questions/35075195/is-there-api-documentation-for-kublet 56 | [spiffe-impl]: https://github.com/spiffe/spire/blob/719c696036a99c0cd918ff4747d5fd7f15c782e4/pkg/agent/plugin/workloadattestor/k8s/k8s.go#L61 57 | [go-audit]: https://github.com/slackhq/go-audit 58 | [uds-pid-lookup]: https://stackoverflow.com/questions/8104904/identify-program-that-connects-to-a-unix-domain-socket -------------------------------------------------------------------------------- /cmd/pid2pod-demo/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 by the contributors. 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 | 15 | // Package main runs "pid2pod-demo", which lists Kubernetes pod metadata for all proceses. 16 | package main 17 | 18 | import ( 19 | "fmt" 20 | "log" 21 | 22 | "github.com/mitchellh/go-ps" 23 | 24 | "github.com/heptiolabs/pid2pod" 25 | ) 26 | 27 | func main() { 28 | processes, err := ps.Processes() 29 | if err != nil { 30 | log.Fatalf("could not list processes: %v", err) 31 | } 32 | for _, proc := range processes { 33 | pid := proc.Pid() 34 | id, err := pid2pod.LookupPod(pid) 35 | if err != nil { 36 | log.Fatalf("could not get ID of process %d: %v", pid, err) 37 | } 38 | if id != nil { 39 | fmt.Printf("PID %d (%s): %+#v\n", pid, proc.Executable(), id) 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pid2pod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 by the contributors. 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 | 15 | // Package pid2pod helps map Linux process IDs (PIDs) into Kubernetes Pod metadata. 16 | package pid2pod 17 | 18 | import ( 19 | "bufio" 20 | "encoding/json" 21 | "fmt" 22 | "io/ioutil" 23 | "net/http" 24 | "os" 25 | "regexp" 26 | 27 | "github.com/pkg/errors" 28 | ) 29 | 30 | // ID identifies a single container running in a Kubernetes Pod 31 | type ID struct { 32 | Namespace string 33 | PodName string 34 | PodUID string 35 | PodLabels map[string]string 36 | ContainerID string 37 | ContainerName string 38 | } 39 | 40 | // LookupPod looks up a process ID from the host PID namespace, returning its Kubernetes identity. 41 | func LookupPod(pid int) (*ID, error) { 42 | // First find the Docker container ID. 43 | cid, err := LookupDockerContainerID(pid) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | // Look up the container ID in the local kubelet API. 49 | resp, err := http.Get(fmt.Sprintf("http://localhost:%v/pods", 10255)) 50 | if err != nil { 51 | return nil, errors.WithMessage(err, "could not lookup container ID in kubelet API") 52 | } 53 | defer resp.Body.Close() 54 | body, err := ioutil.ReadAll(resp.Body) 55 | if err != nil { 56 | return nil, errors.WithMessage(err, "could not read response from kubelet API") 57 | } 58 | var podInfo *podList 59 | if err := json.Unmarshal(body, &podInfo); err != nil { 60 | return nil, errors.WithMessage(err, "could not unmarshal response from kubelet API") 61 | } 62 | 63 | for _, item := range podInfo.Items { 64 | for _, status := range item.Status.ContainerStatuses { 65 | if status.ContainerID == "docker://"+cid { 66 | return &ID{ 67 | Namespace: item.Metadata.Namespace, 68 | PodName: item.Metadata.Name, 69 | PodUID: item.Metadata.UID, 70 | PodLabels: item.Metadata.Labels, 71 | ContainerID: cid, 72 | ContainerName: status.Name, 73 | }, nil 74 | } 75 | } 76 | } 77 | return nil, nil 78 | } 79 | 80 | // LookupDockerContainerID looks up a process ID from the host PID namespace, 81 | // returning its Docker container ID. 82 | func LookupDockerContainerID(pid int) (string, error) { 83 | f, err := os.Open(fmt.Sprintf("/proc/%d/cgroup", pid)) 84 | if err != nil { 85 | // this is normal, it just means the PID no longer exists 86 | return "", nil 87 | } 88 | defer f.Close() 89 | 90 | scanner := bufio.NewScanner(f) 91 | for scanner.Scan() { 92 | line := scanner.Text() 93 | parts := dockerPattern.FindStringSubmatch(line) 94 | if parts != nil { 95 | return parts[1], nil 96 | } 97 | parts = kubePattern.FindStringSubmatch(line) 98 | if parts != nil { 99 | return parts[1], nil 100 | } 101 | } 102 | return "", nil 103 | } 104 | 105 | var ( 106 | kubePattern = regexp.MustCompile(`\d+:.+:/kubepods/[^/]+/pod[^/]+/([0-9a-f]{64})`) 107 | dockerPattern = regexp.MustCompile(`\d+:.+:/docker/pod[^/]+/([0-9a-f]{64})`) 108 | ) 109 | 110 | type podList struct { 111 | // We only care about namespace, serviceAccountName and containerID 112 | Metadata struct { 113 | } `json:"metadata"` 114 | Items []struct { 115 | Metadata struct { 116 | Namespace string `json:"namespace"` 117 | Name string `json:"name"` 118 | UID string `json:"uid"` 119 | Labels map[string]string `json:"labels"` 120 | } `json:"metadata"` 121 | Spec struct { 122 | ServiceAccountName string `json:"serviceAccountName"` 123 | } `json:"spec"` 124 | Status struct { 125 | ContainerStatuses []struct { 126 | ContainerID string `json:"containerID"` 127 | Name string `json:"name"` 128 | } `json:"containerStatuses"` 129 | } `json:"status"` 130 | } `json:"items"` 131 | } 132 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-ps/.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant/ 2 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-ps/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.2.1 5 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-ps/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Mitchell Hashimoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-ps/README.md: -------------------------------------------------------------------------------- 1 | # Process List Library for Go 2 | 3 | go-ps is a library for Go that implements OS-specific APIs to list and 4 | manipulate processes in a platform-safe way. The library can find and 5 | list processes on Linux, Mac OS X, Solaris, and Windows. 6 | 7 | If you're new to Go, this library has a good amount of advanced Go educational 8 | value as well. It uses some advanced features of Go: build tags, accessing 9 | DLL methods for Windows, cgo for Darwin, etc. 10 | 11 | How it works: 12 | 13 | * **Darwin** uses the `sysctl` syscall to retrieve the process table. 14 | * **Unix** uses the procfs at `/proc` to inspect the process tree. 15 | * **Windows** uses the Windows API, and methods such as 16 | `CreateToolhelp32Snapshot` to get a point-in-time snapshot of 17 | the process table. 18 | 19 | ## Installation 20 | 21 | Install using standard `go get`: 22 | 23 | ``` 24 | $ go get github.com/mitchellh/go-ps 25 | ... 26 | ``` 27 | 28 | ## TODO 29 | 30 | Want to contribute? Here is a short TODO list of things that aren't 31 | implemented for this library that would be nice: 32 | 33 | * FreeBSD support 34 | * Plan9 support 35 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-ps/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! 5 | VAGRANTFILE_API_VERSION = "2" 6 | 7 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 8 | config.vm.box = "chef/ubuntu-12.04" 9 | 10 | config.vm.provision "shell", inline: $script 11 | 12 | ["vmware_fusion", "vmware_workstation"].each do |p| 13 | config.vm.provider "p" do |v| 14 | v.vmx["memsize"] = "1024" 15 | v.vmx["numvcpus"] = "2" 16 | v.vmx["cpuid.coresPerSocket"] = "1" 17 | end 18 | end 19 | end 20 | 21 | $script = <