├── .github
├── ISSUE_TEMPLATE
│ ├── bug-report.yaml
│ └── enhancement.yaml
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── ci-bot.yml
│ ├── releases-images.yml
│ ├── releases-package.yml
│ ├── releases-source.yml
│ └── verify.yml
├── .gitignore
├── Makefile
├── OWNERS
├── README.md
├── deb
├── kubeadm
│ ├── debian
│ │ ├── changelog
│ │ ├── compat
│ │ ├── control
│ │ ├── copyright
│ │ ├── kubeadm.install
│ │ ├── postinst
│ │ ├── rules
│ │ └── source
│ │ │ └── format
│ └── etc
│ │ └── systemd
│ │ └── system
│ │ └── kubelet.service.d
│ │ └── 10-kubeadm.conf
├── kubectl
│ └── debian
│ │ ├── changelog
│ │ ├── compat
│ │ ├── control
│ │ ├── copyright
│ │ ├── kubectl.install
│ │ ├── postinst
│ │ ├── rules
│ │ └── source
│ │ └── format
└── kubelet
│ ├── debian
│ ├── changelog
│ ├── compat
│ ├── control
│ ├── copyright
│ ├── kubelet.install
│ ├── postinst
│ ├── rules
│ └── source
│ │ └── format
│ └── lib
│ └── systemd
│ └── system
│ └── kubelet.service
├── hack
├── build_binaries.sh
├── build_image.sh
├── checkout.sh
├── format_all_patch.sh
├── format_patch.sh
├── gen_verify_workflows.sh
├── git_sync_repos.sh
├── image_manifest_push.sh
├── image_manifest_retags.sh
├── image_other.sh
├── image_tag.sh
├── install_etcd.sh
├── kit.sh
├── pkg_deb.sh
├── pkg_rpm.sh
├── public_source.sh
├── test.sh
├── test_cmd.sh
├── test_e2e.sh
├── test_e2e_node.sh
├── test_integration.sh
├── verify_build.sh
├── verify_build_client.sh
├── verify_build_image.sh
├── verify_build_server.sh
├── verify_patch.sh
├── verify_patch_format.sh
├── verify_pkg_deb_client.sh
├── verify_pkg_deb_server.sh
├── verify_pkg_rpm_client.sh
├── verify_pkg_rpm_server.sh
└── verify_releases.sh
├── patches
├── CVE-2019-1002100.1.10.patch
├── CVE-2019-1002101.1.10.patch
├── CVE-2019-11246.1.10.patch
├── CVE-2019-11246.1.11.patch
├── CVE-2019-11247.1.11.patch
├── CVE-2019-11248.1.11.patch
├── CVE-2019-11249.1.10.patch
├── CVE-2019-11249.1.12.patch
├── CVE-2019-11251.1.10.patch
├── CVE-2020-8552.1.11.patch
├── CVE-2020-8552.1.13.patch
├── CVE-2020-8552.1.14.patch
├── CVE-2020-8554.1.18.patch
├── CVE-2020-8554.1.19.patch
├── CVE-2020-8555.1.14.patch
├── CVE-2020-8558.1.12.patch
├── CVE-2020-8559.1.12.patch
├── CVE-2020-8559.1.13.patch
├── CVE-2021-25741.1.18.patch
├── codegens-to-scripts.1.24.patch
├── codegens-to-scripts.1.25.patch
├── fix-etcd-health.1.11.patch
├── fix-etcd-health.1.16.patch
├── fix-etcd-put-key.1.11.patch
├── fix-etcd-put-key.1.23.patch
├── fix-etcd-put-key.1.24.patch
├── fix-image-name.1.12.patch
├── fix-kubectl-convert-97644.1.20.patch
├── fix-missing-env-91500.1.18.patch
├── fix-run-docker.1.24.patch
├── fix-test.1.16.patch
├── no-delete-images.1.10.patch
├── no-delete-images.1.12.patch
├── no-delete-images.1.15.patch
├── no-delete-images.1.24.patch
├── nokmem.1.13.patch
├── nokmem.1.20.patch
└── update-kube-proxy-iptables.1.18.patch
├── releases.yml
└── rpm
├── kubeadm
├── 10-kubeadm.conf
└── kubeadm.spec
├── kubectl
└── kubectl.spec
└── kubelet
├── kubelet.env
├── kubelet.service
└── kubelet.spec
/.github/ISSUE_TEMPLATE/bug-report.yaml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: Report a bug encountered while operating Kubernetes
3 | labels:
4 | - kind/bug
5 | body:
6 | - type: textarea
7 | id: problem
8 | attributes:
9 | label: What happened?
10 | description: Please provide as much info as possible.
11 | validations:
12 | required: true
13 |
14 | - type: textarea
15 | id: expected
16 | attributes:
17 | label: What did you expect to happen?
18 | validations:
19 | required: true
20 |
21 | - type: textarea
22 | id: reproduce
23 | attributes:
24 | label: How can we reproduce it (as minimally and precisely as possible)?
25 | validations:
26 | required: true
27 |
28 | - type: textarea
29 | id: additional
30 | attributes:
31 | label: Anything else we need to know?
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/enhancement.yaml:
--------------------------------------------------------------------------------
1 | name: Enhancement Tracking Issue
2 | description: Provide supporting details for a feature in development
3 | labels:
4 | - kind/feature
5 | body:
6 | - type: textarea
7 | id: feature
8 | attributes:
9 | label: What would you like to be added?
10 | description: Feature requests are unlikely to make progress as issues.
11 | validations:
12 | required: true
13 |
14 | - type: textarea
15 | id: rationale
16 | attributes:
17 | label: Why is this needed?
18 | validations:
19 | required: true
20 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | #### What type of PR is this?
2 |
3 |
10 |
11 | #### What this PR does / why we need it:
12 |
13 | #### Which issue(s) this PR fixes:
14 |
18 | Fixes #
19 |
20 | #### Special notes for your reviewer:
21 |
22 | #### Does this PR introduce a user-facing change?
23 |
28 | ```release-note
29 |
30 | ```
31 |
--------------------------------------------------------------------------------
/.github/workflows/ci-bot.yml:
--------------------------------------------------------------------------------
1 | name: CI Bot
2 | on:
3 | issue_comment:
4 | types:
5 | - created
6 | pull_request_review_comment:
7 | types:
8 | - created
9 | issues:
10 | types:
11 | - opened
12 | pull_request:
13 | types:
14 | - opened
15 |
16 | env:
17 | # This plugins is for anyone who can use it
18 | PLUGINS: |-
19 | assign
20 | auto-cc
21 | cc
22 | label-kind
23 | label-bug
24 | label-documentation
25 | label-enhancement
26 | label-question
27 |
28 | # This plugins is for organization member or repository member
29 | MEMBERS_PLUGINS: |-
30 | label-duplicate
31 | label-good-first-issue
32 | label-help-wanted
33 | label-invalid
34 | label-kind
35 | label-wontfix
36 | lifecycle
37 |
38 | # This plugins is for in the REVIEWERS environment variable
39 | REVIEWERS_PLUGINS: |-
40 | retitle
41 | # This plugins is for in the APPROVERS environment variable
42 | APPROVERS_PLUGINS: |-
43 | merge
44 | # This plugins is for in the MAINTAINERS environment variable
45 | MAINTAINERS_PLUGINS: |-
46 | milestone
47 | # This plugins is for organization owner or repository owner
48 | OWNERS_PLUGINS: ""
49 |
50 | REVIEWERS: |-
51 | pacoxu
52 | wzshiming
53 | APPROVERS: |-
54 | pacoxu
55 | wzshiming
56 | MAINTAINERS: |-
57 | pacoxu
58 | wzshiming
59 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
60 | GH_REPOSITORY: ${{ github.repository }}
61 | DETAILS: |-
62 |
63 | Details
64 | Instructions for interacting with me using comments are available here.
65 | If you have questions or suggestions related to my behavior, please file an issue against the [gh-ci-bot](https://github.com/wzshiming/gh-ci-bot) repository.
66 |
67 | jobs:
68 |
69 | issue_opened:
70 | name: Issue Opened
71 | if: ${{ github.event_name == 'issues' }}
72 | runs-on: ubuntu-latest
73 | steps:
74 | - uses: wzshiming/gh-ci-bot@v1
75 | env:
76 | LOGIN: ${{ github.event.issue.user.login }}
77 | MESSAGE: ${{ github.event.issue.body }}
78 | ISSUE_NUMBER: ${{ github.event.issue.number }}
79 | AUTHOR_ASSOCIATION: ${{ github.event.issue.author_association }}
80 | ISSUE_KIND: issue
81 | TYPE: created
82 | GREETING: |-
83 | Hi @${{ github.event.issue.user.login }},
84 | Thanks for opening an issue!
85 | We will look into it as soon as possible.
86 | pr_opened:
87 | name: PR Opened
88 | if: ${{ github.event_name == 'pull_request' }}
89 | runs-on: ubuntu-latest
90 | steps:
91 | - uses: wzshiming/gh-ci-bot@v1
92 | env:
93 | LOGIN: ${{ github.event.pull_request.user.login }}
94 | MESSAGE: ${{ github.event.pull_request.body }}
95 | ISSUE_NUMBER: ${{ github.event.pull_request.number }}
96 | AUTHOR_ASSOCIATION: ${{ github.event.pull_request.author_association }}
97 | ISSUE_KIND: pr
98 | TYPE: created
99 | GREETING: |-
100 | Hi @${{ github.event.pull_request.user.login }},
101 | Thanks for your pull request!
102 | If the PR is ready, use the `/auto-cc` command to assign Reviewer to Review.
103 | We will review it shortly.
104 | issue_commented:
105 | name: Issue Commented
106 | if: ${{ github.event_name == 'issue_comment' && !github.event.issue.pull_request }}
107 | runs-on: ubuntu-latest
108 | steps:
109 | - uses: wzshiming/gh-ci-bot@v1
110 | env:
111 | LOGIN: ${{ github.event.comment.user.login }}
112 | MESSAGE: ${{ github.event.comment.body }}
113 | ISSUE_NUMBER: ${{ github.event.issue.number }}
114 | AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
115 | ISSUE_KIND: issue
116 | TYPE: comment
117 |
118 | pr_review_commented:
119 | name: PR Review Commented
120 | if: ${{ github.event_name == 'pull_request_review_comment' }}
121 | runs-on: ubuntu-latest
122 | steps:
123 | - uses: wzshiming/gh-ci-bot@v1
124 | env:
125 | LOGIN: ${{ github.event.comment.user.login }}
126 | MESSAGE: ${{ github.event.comment.body }}
127 | ISSUE_NUMBER: ${{ github.event.pull_request.number }}
128 | AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
129 | ISSUE_KIND: pr
130 | TYPE: comment
131 |
132 | pr_commented:
133 | name: PR Commented
134 | if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }}
135 | runs-on: ubuntu-latest
136 | steps:
137 | - uses: wzshiming/gh-ci-bot@v1
138 | env:
139 | LOGIN: ${{ github.event.comment.user.login }}
140 | MESSAGE: ${{ github.event.comment.body }}
141 | ISSUE_NUMBER: ${{ github.event.issue.number }}
142 | AUTHOR_ASSOCIATION: ${{ github.event.comment.author_association }}
143 | ISSUE_KIND: pr
144 | TYPE: comment
145 |
--------------------------------------------------------------------------------
/.github/workflows/releases-images.yml:
--------------------------------------------------------------------------------
1 | name: Releases Images
2 |
3 | on:
4 | push:
5 | tags:
6 | - v*
7 |
8 | workflow_dispatch:
9 |
10 | jobs:
11 | Images:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: Install dependent
16 | run: |
17 | make dependent
18 | - name: Config Github
19 | run: |
20 | git config --global user.email "noreply@github.com"
21 | git config --global user.name "GitHub"
22 | - name: Checkout
23 | run: |
24 | make $(basename ${GITHUB_REF})
25 | - name: Build images
26 | run: |
27 | make build-image
28 | - name: Login registry
29 | run: |
30 | echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
31 | - name: Push images
32 | run: |
33 | OLD_REGISTRY=registry.k8s.io REGISTRY="ghcr.io/$(echo ${{ github.repository }} | tr "A-Z" "a-z")" make push-image
34 | - name: Sync others image
35 | env:
36 | GH_ID: ${{ github.actor }}
37 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38 | run: |
39 | sudo mkdir -p /run/containers && sudo chmod 777 /run/containers
40 | skopeo login -u ${GH_ID} -p ${GH_TOKEN} ghcr.io
41 | REGISTRY="ghcr.io/$(echo ${{ github.repository }} | tr "A-Z" "a-z")" make image-other
42 |
--------------------------------------------------------------------------------
/.github/workflows/releases-package.yml:
--------------------------------------------------------------------------------
1 | name: Releases Packages
2 |
3 | on:
4 | push:
5 | tags:
6 | - v*
7 |
8 | workflow_dispatch:
9 |
10 | jobs:
11 | Build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: Install dependent
16 | run: |
17 | make dependent
18 | - name: Config Github
19 | run: |
20 | git config --global user.email "noreply@github.com"
21 | git config --global user.name "GitHub"
22 | - name: Checkout
23 | run: |
24 | make $(basename ${GITHUB_REF})
25 | - name: Build binaries
26 | run: |
27 | make build-binaries
28 |
29 | - name: Package rpm
30 | run: |
31 | make pkg-rpm
32 | - name: Sync repository
33 | env:
34 | BRANCH_PREFIX: "rpm-"
35 | REPOS: "rpm"
36 | run: |
37 | GH_TOKEN="${GH_TOKEN:-${{ secrets.GITHUB_TOKEN }}}" SOURCE="${SOURCE:-https://github.com/${{ github.repository }}}" make repos-sync
38 |
39 | - name: Package deb
40 | run: |
41 | make pkg-deb
42 | - name: Sync repository
43 | env:
44 | BRANCH_PREFIX: "deb-"
45 | REPOS: "deb"
46 | run: |
47 | GH_TOKEN="${GH_TOKEN:-${{ secrets.GITHUB_TOKEN }}}" SOURCE="${SOURCE:-https://github.com/${{ github.repository }}}" make repos-sync
48 |
--------------------------------------------------------------------------------
/.github/workflows/releases-source.yml:
--------------------------------------------------------------------------------
1 | name: Releases Source
2 |
3 | on:
4 | push:
5 | tags:
6 | - v*
7 |
8 | workflow_dispatch:
9 |
10 | jobs:
11 | Build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: Install dependent
16 | run: |
17 | make dependent
18 | - name: Config Github
19 | run: |
20 | git config --global user.email "noreply@github.com"
21 | git config --global user.name "GitHub"
22 | - name: Checkout
23 | run: |
24 | make $(basename ${GITHUB_REF})
25 | - name: Release source
26 | env:
27 | SOURCE: https://github.com/klts-io/kubernetes
28 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
29 | run: |
30 | make public-source
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | kit/
2 | src/
3 | output/
4 | release/
5 | rpmbuild/
6 | debbuild/
7 | repos/
8 | tmp/
9 | .*
10 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | v%:
3 | @echo Checkout to $@
4 | ./hack/checkout.sh $@
5 |
6 | dependent:
7 | pip3 install yq
8 | ./hack/kit.sh
9 |
10 | .PHONY: public-source
11 | public-source:
12 | @echo Public Source
13 | ./hack/public_source.sh
14 |
15 | .PHONY: build-binaries
16 | build-binaries:
17 | @echo Build binaries
18 | ./hack/build_binaries.sh
19 |
20 | .PHONY: pkg-rpm
21 | pkg-rpm:
22 | ./hack/pkg_rpm.sh
23 |
24 | .PHONY: pkg-deb
25 | pkg-deb:
26 | ./hack/pkg_deb.sh
27 |
28 | .PHONY: repos-sync
29 | repos-sync:
30 | ./hack/git_sync_repos.sh
31 |
32 | .PHONY: build-image
33 | build-image:
34 | @echo Build image
35 | ./hack/build_image.sh
36 |
37 | .PHONY: image-other
38 | image-other:
39 | ./hack/image_other.sh
40 |
41 | .PHONY: verify
42 | verify: verify-patch
43 |
44 | .PHONY: verify-patch
45 | verify-patch:
46 | ./hack/verify_patch.sh
47 |
48 | .PHONY: verify-releases
49 | verify-releases:
50 | ./hack/verify_releases.sh
51 |
52 | .PHONY: verify-patch-format
53 | verify-patch-format:
54 | ./hack/verify_patch_format.sh
55 |
56 | .PHONY: verify-build
57 | verify-build:
58 | ./hack/verify_build.sh
59 |
60 | .PHONY: verify-build-client
61 | verify-build-client:
62 | ./hack/verify_build_client.sh
63 |
64 | .PHONY: verify-build-server
65 | verify-build-server:
66 | ./hack/verify_build_server.sh
67 |
68 | .PHONY: verify-pkg-rpm-client
69 | verify-pkg-rpm-client:
70 | ./hack/verify_pkg_rpm_client.sh
71 |
72 | .PHONY: verify-pkg-rpm-server
73 | verify-pkg-rpm-server:
74 | ./hack/verify_pkg_rpm_server.sh
75 |
76 | .PHONY: verify-pkg-deb-client
77 | verify-pkg-deb-client:
78 | ./hack/verify_pkg_deb_client.sh
79 |
80 | .PHONY: verify-pkg-deb-server
81 | verify-pkg-deb-server:
82 | ./hack/verify_pkg_deb_server.sh
83 |
84 | .PHONY: verify-build-image
85 | verify-build-image:
86 | ./hack/verify_build_image.sh
87 |
88 | .PHONY: gen-verify-workflows
89 | gen-verify-workflows:
90 | ./hack/gen_verify_workflows.sh > .github/workflows/verify.yml
91 |
92 | .PHONY: push-image
93 | push-image:
94 | ./hack/image_tag.sh && ./hack/image_manifest_push.sh
95 |
96 | .PHONY: format-all-patch
97 | format-all-patch:
98 | ./hack/format_all_patch.sh
99 |
100 | .PHONY: test
101 | test:
102 | ./hack/test.sh
103 |
104 | .PHONY: test-cmd
105 | test-cmd:
106 | ./hack/test_cmd.sh
107 |
108 | .PHONY: test-integration
109 | test-integration:
110 | ./hack/test_integration.sh
111 |
112 | .PHONY: test-e2e
113 | test-e2e:
114 | ./hack/test_e2e.sh
115 |
116 | .PHONY: test-e2e-node
117 | test-e2e-node:
118 | ./hack/test_e2e_node.sh
119 |
120 | .PHONY: install-etcd
121 | install-etcd:
122 | ./hack/install_etcd.sh
123 |
--------------------------------------------------------------------------------
/OWNERS:
--------------------------------------------------------------------------------
1 | # See the OWNERS docs at https://go.klts.io/owners
2 |
3 | approvers:
4 | - wzshiming
5 | - kerthcet
6 | - calvin0327
7 | reviewers:
8 | - mengjiao-liu
9 | - pacoxu
10 | - Ericwvi
11 | - jonyhy96
12 | - cyclinder
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # KLTS
4 | KLTS, known as Kubernetes Long Term Support, provides free maintenance support for early Kubernetes versions for up to three years, actively fix the CVE vulnerabilities and critical bugs, to help many enterprise users to stay with early Kubernetes versions.
5 |
6 | ----
7 |
8 | ## To start using KLTS
9 |
10 | ### Available KLTS Versions
11 | Below lists the status of each release image and package and you can click any to learn the detailed logs.
12 | | |Images|Packages|
13 | |-|-|-|
14 | |v1.28.15|[](https://klts.io/docs/kubernetes/releases/v1.28/v1.28.15-lts.0/)|[](https://klts.io/docs/kubernetes/releases/v1.28/v1.28.15-lts.0/)|
15 | |v1.27.16|[](https://klts.io/docs/kubernetes/releases/v1.27/v1.27.16-lts.0/)|[](https://klts.io/docs/kubernetes/releases/v1.27/v1.27.16-lts.0/)|
16 | |v1.26.15|[](https://klts.io/docs/kubernetes/releases/v1.26/v1.26.15-lts.0/)|[](https://klts.io/docs/kubernetes/releases/v1.26/v1.26.15-lts.0/)|
17 | |v1.25.16|[](https://klts.io/docs/kubernetes/releases/v1.25/v1.25.16-lts.0/)|[](https://klts.io/docs/kubernetes/releases/v1.25/v1.25.16-lts.0/)|
18 | |v1.24.17|[](https://klts.io/docs/kubernetes/releases/v1.24/v1.24.17-lts.0/)|[](https://klts.io/docs/kubernetes/releases/v1.24/v1.24.17-lts.0/)|
19 | |v1.23.17|[](https://klts.io/docs/kubernetes/releases/v1.23/v1.23.17-lts.0/)|[](https://klts.io/docs/kubernetes/releases/v1.23/v1.23.17-lts.0/)|
20 | |v1.22.17|[](https://klts.io/docs/kubernetes/releases/v1.22/v1.22.17-lts.0/)|[](https://klts.io/docs/kubernetes/releases/v1.22/v1.22.17-lts.0/)|
21 | |v1.21.14|[](https://klts.io/docs/kubernetes/releases/v1.21/v1.21.14-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.21/v1.21.14-lts.1/)|
22 | |v1.20.15|[](https://klts.io/docs/kubernetes/releases/v1.20/v1.20.15-lts.2/)|[](https://klts.io/docs/kubernetes/releases/v1.20/v1.20.15-lts.2/)|
23 | |v1.19.16|[](https://klts.io/docs/kubernetes/releases/v1.19/v1.19.16-lts.3/)|[](https://klts.io/docs/kubernetes/releases/v1.19/v1.19.16-lts.3/)|
24 | |v1.18.20|[](https://klts.io/docs/kubernetes/releases/v1.18/v1.18.20-lts.2/)|[](https://klts.io/docs/kubernetes/releases/v1.18/v1.18.20-lts.2/)|
25 | |v1.17.17|[](https://klts.io/docs/kubernetes/releases/v1.17/v1.17.17-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.17/v1.17.17-lts.1/)|
26 | |v1.16.15|[](https://klts.io/docs/kubernetes/releases/v1.16/v1.16.15-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.16/v1.16.15-lts.1/)|
27 | |v1.15.12|[](https://klts.io/docs/kubernetes/releases/v1.15/v1.15.12-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.15/v1.15.12-lts.1/)|
28 | |v1.14.10|[](https://klts.io/docs/kubernetes/releases/v1.14/v1.14.10-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.14/v1.14.10-lts.1/)|
29 | |v1.13.12|[](https://klts.io/docs/kubernetes/releases/v1.13/v1.13.12-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.13/v1.13.12-lts.1/)|
30 | |v1.12.10|[](https://klts.io/docs/kubernetes/releases/v1.12/v1.12.10-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.12/v1.12.10-lts.1/)|
31 | |v1.11.10|[](https://klts.io/docs/kubernetes/releases/v1.11/v1.11.10-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.11/v1.11.10-lts.1/)|
32 | |v1.10.13|[](https://klts.io/docs/kubernetes/releases/v1.10/v1.10.13-lts.1/)|[](https://klts.io/docs/kubernetes/releases/v1.10/v1.10.13-lts.1/)|
33 |
34 | ### CVE Source
35 |
36 | - [CVEs that were cherry-pick approved and merged after pull requests](https://github.com/kubernetes/kubernetes/pulls?q=is%3Apr+is%3Amerged+label%3Acherry-pick-approved+CVE)
37 |
38 | - [CVEs that were found and fixed recently](https://www.cvedetails.com/vulnerability-list/vendor_id-15867/product_id-34016/Kubernetes-Kubernetes.html)
39 |
40 | - [Kubernetes-related CVEs that were found and listed on cve.org recently](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=Kubernetes)
41 |
42 |
43 |
44 | ### Documents
45 |
46 | - [Portal and Docs](https://klts.io/docs/)
47 | - [Install Guide](https://klts.io/docs/install/)
48 |
49 |
50 | -----------------------
51 |
52 | ## To start contributing KLTS
53 |
54 | ### Check out the specified patch release
55 |
56 | You can directly check out the specified release by running the following code. For details about the releases provided by KLTS, see [./releases.yml](https://github.com/klts-io/kubernetes-lts/blob/master/releases.yml)
57 |
58 | ``` bash
59 | make v1.19.16-lts.3
60 | ```
61 |
62 | ### Build
63 |
64 | Since the repos branch is used as a software source for RPM and DEB and direct cloning is very large, you can try to only clone a single branch as follows.
65 |
66 | ``` bash
67 | git clone --single-branch -b main https://github.com/klts-io/kubernetes-lts
68 | ```
69 |
70 | #### Build image
71 | Run the following code to build your image:
72 |
73 | ``` bash
74 | make build-image
75 | ```
76 |
77 | Check more images from [Images artifacts](https://github.com/orgs/klts-io/packages?repo_name=kubernetes-lts).
78 |
79 | #### Build client and server
80 | Run the following code to build the client and server:
81 |
82 | ``` bash
83 | make build-binaries
84 | ```
85 | #### Official patch release
86 | For details about Kubernetes patch releases, see [patch release](https://kubernetes.io/releases/patch-releases/).
87 |
88 | ## Contributors
89 |
90 |
91 |
92 |
93 |
94 | Made with [contrib.rocks](https://contrib.rocks).
95 |
96 | ## License
97 | Copyright 2022 the KLTS.io Authors. All rights reserved.
98 |
99 | Licensed under the Apache License, Version 2.0.
100 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/changelog:
--------------------------------------------------------------------------------
1 | kubeadm (%{_version}-%{_release}) lts; urgency=medium
2 |
3 | * https://git.k8s.io/kubernetes/CHANGELOG/README.md
4 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/compat:
--------------------------------------------------------------------------------
1 | 9
2 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/control:
--------------------------------------------------------------------------------
1 | Source: kubeadm
2 | Section: misc
3 | Priority: optional
4 | Maintainer: Kubernetes Authors
5 | Build-Depends: ca-certificates, debhelper (>= 8.0.0)
6 | Standards-Version: 3.9.4
7 | Homepage: https://kubernetes.io
8 | Vcs-Git: https://github.com/kubernetes/kubernetes.git
9 | Vcs-Browser: https://github.com/kubernetes/kubernetes
10 |
11 | Package: kubeadm
12 | Architecture: %{_arch}
13 | Depends: kubelet (>= 1.10.0), kubectl (>= 1.10.0), kubernetes-cni (>= 0.8.6), cri-tools (>= 1.13.0), ${misc:Depends}
14 | Description: Kubernetes Cluster Bootstrapping Tool
15 | The Kubernetes command line tool for bootstrapping a Kubernetes cluster.
16 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/copyright:
--------------------------------------------------------------------------------
1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2 | Upstream-Name: kubeadm
3 | Source: https://github.com/kubernetes/kubernetes
4 |
5 | Files: *
6 | Copyright: 2016 The Kubernetes Authors.
7 | License: Apache-2.0
8 | Licensed under the Apache License, Version 2.0 (the "License");
9 | you may not use this file except in compliance with the License.
10 | You may obtain a copy of the License at
11 | .
12 | http://www.apache.org/licenses/LICENSE-2.0
13 | .
14 | Unless required by applicable law or agreed to in writing, software
15 | distributed under the License is distributed on an "AS IS" BASIS,
16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | See the License for the specific language governing permissions and
18 | limitations under the License.
19 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/kubeadm.install:
--------------------------------------------------------------------------------
1 | usr/bin/kubeadm usr/bin/
2 | etc/systemd/system/kubelet.service.d/10-kubeadm.conf etc/systemd/system/kubelet.service.d/
3 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/postinst:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # see: dh_installdeb(1)
3 |
4 | set -o errexit
5 | set -o nounset
6 |
7 | # summary of how this script can be called:
8 | # * `configure'
9 | # * `abort-upgrade'
10 | # * `abort-remove' `in-favour'
11 | #
12 | # * `abort-remove'
13 | # * `abort-deconfigure' `in-favour'
14 | # `removing'
15 | #
16 | # for details, see https://www.debian.org/doc/debian-policy/ or
17 | # the debian-policy package
18 |
19 |
20 | case "$1" in
21 | configure)
22 | # because kubeadm package adds kubelet drop-ins, we must daemon-reload
23 | # and restart kubelet now. restarting kubelet is ok because kubelet
24 | # postinst configure step auto-starts it.
25 | systemctl daemon-reload 2>/dev/null || true
26 | systemctl restart kubelet 2>/dev/null || true
27 | ;;
28 |
29 | abort-upgrade|abort-remove|abort-deconfigure)
30 | ;;
31 |
32 | *)
33 | echo "postinst called with unknown argument \`$1'" >&2
34 | exit 1
35 | ;;
36 | esac
37 |
38 | # dh_installdeb will replace this with shell code automatically
39 | # generated by other debhelper scripts.
40 |
41 | #DEBHELPER#
42 |
43 | exit 0
44 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # -*- makefile -*-
3 |
4 | #export DH_VERBOSE=1
5 | KUBE_LOCAL_ARTIFACTS?=
6 |
7 | build:
8 | echo noop
9 |
10 | binary:
11 | mkdir -p usr/bin
12 | cp kubeadm usr/bin/kubeadm
13 | chmod +x usr/bin/kubeadm
14 | dh_testroot
15 | dh_auto_install
16 | dh_shlibdeps
17 | dh_install
18 | dh_installdeb
19 | dh_gencontrol
20 | dh_md5sums
21 | dh_builddeb
22 |
23 | %:
24 | dh $@
25 |
--------------------------------------------------------------------------------
/deb/kubeadm/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (native)
2 |
--------------------------------------------------------------------------------
/deb/kubeadm/etc/systemd/system/kubelet.service.d/10-kubeadm.conf:
--------------------------------------------------------------------------------
1 | # Note: This dropin only works with kubeadm and kubelet v1.11+
2 | [Service]
3 | Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
4 | Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
5 | # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
6 | EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
7 | # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
8 | # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
9 | EnvironmentFile=-/etc/default/kubelet
10 | ExecStart=
11 | ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
12 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/changelog:
--------------------------------------------------------------------------------
1 | kubectl (%{_version}-%{_release}) lts; urgency=medium
2 |
3 | * https://git.k8s.io/kubernetes/CHANGELOG/README.md
4 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/compat:
--------------------------------------------------------------------------------
1 | 9
2 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/control:
--------------------------------------------------------------------------------
1 | Source: kubectl
2 | Section: misc
3 | Priority: optional
4 | Maintainer: Kubernetes Authors
5 | Build-Depends: ca-certificates, debhelper (>= 8.0.0)
6 | Standards-Version: 3.9.4
7 | Homepage: https://kubernetes.io
8 | Vcs-Git: https://github.com/kubernetes/kubernetes.git
9 | Vcs-Browser: https://github.com/kubernetes/kubernetes
10 |
11 | Package: kubectl
12 | Architecture: %{_arch}
13 | Depends: ${misc:Depends}
14 | Description: Kubernetes Command Line Tool
15 | The Kubernetes command line tool for interacting with the Kubernetes API.
16 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/copyright:
--------------------------------------------------------------------------------
1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2 | Upstream-Name: kubectl
3 | Source: https://github.com/kubernetes/kubernetes
4 |
5 | Files: *
6 | Copyright: 2016 The Kubernetes Authors.
7 | License: Apache-2.0
8 | Licensed under the Apache License, Version 2.0 (the "License");
9 | you may not use this file except in compliance with the License.
10 | You may obtain a copy of the License at
11 | .
12 | http://www.apache.org/licenses/LICENSE-2.0
13 | .
14 | Unless required by applicable law or agreed to in writing, software
15 | distributed under the License is distributed on an "AS IS" BASIS,
16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | See the License for the specific language governing permissions and
18 | limitations under the License.
19 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/kubectl.install:
--------------------------------------------------------------------------------
1 | usr/bin/kubectl usr/bin/
2 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/postinst:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # see: dh_installdeb(1)
3 |
4 | set -o errexit
5 | set -o nounset
6 |
7 | # summary of how this script can be called:
8 | # * `configure'
9 | # * `abort-upgrade'
10 | # * `abort-remove' `in-favour'
11 | #
12 | # * `abort-remove'
13 | # * `abort-deconfigure' `in-favour'
14 | # `removing'
15 | #
16 | # for details, see https://www.debian.org/doc/debian-policy/ or
17 | # the debian-policy package
18 |
19 |
20 | case "$1" in
21 | configure)
22 | ;;
23 |
24 | abort-upgrade|abort-remove|abort-deconfigure)
25 | ;;
26 |
27 | *)
28 | echo "postinst called with unknown argument \`$1'" >&2
29 | exit 1
30 | ;;
31 | esac
32 |
33 | # dh_installdeb will replace this with shell code automatically
34 | # generated by other debhelper scripts.
35 |
36 | #DEBHELPER#
37 |
38 | exit 0
39 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # -*- makefile -*-
3 |
4 | #export DH_VERBOSE=1
5 |
6 | build:
7 | echo noop
8 |
9 | binary:
10 | mkdir -p usr/bin
11 | cp kubectl usr/bin/kubectl
12 | chmod +x usr/bin/kubectl
13 | dh_testroot
14 | dh_auto_install
15 | dh_shlibdeps
16 | dh_install
17 | dh_installdeb
18 | dh_gencontrol
19 | dh_md5sums
20 | dh_builddeb
21 |
22 | %:
23 | dh $@
24 |
--------------------------------------------------------------------------------
/deb/kubectl/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (native)
2 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/changelog:
--------------------------------------------------------------------------------
1 | kubelet (%{_version}-%{_release}) lts; urgency=medium
2 |
3 | * https://git.k8s.io/kubernetes/CHANGELOG/README.md
4 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/compat:
--------------------------------------------------------------------------------
1 | 9
2 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/control:
--------------------------------------------------------------------------------
1 | Source: kubelet
2 | Section: misc
3 | Priority: optional
4 | Maintainer: Kubernetes Authors
5 | Build-Depends: ca-certificates, debhelper (>= 9.20160709)
6 | Standards-Version: 3.9.4
7 | Homepage: https://kubernetes.io
8 | Vcs-Git: https://github.com/kubernetes/kubernetes.git
9 | Vcs-Browser: https://github.com/kubernetes/kubernetes
10 |
11 | Package: kubelet
12 | Architecture: %{_arch}
13 | Depends: iptables (>= 1.4.21), kubernetes-cni (>= 0.8.6), iproute2, socat, util-linux, mount, ebtables, ethtool, conntrack, ${misc:Depends}
14 | Description: Kubernetes Node Agent
15 | The node agent of Kubernetes, the container cluster manager
16 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/copyright:
--------------------------------------------------------------------------------
1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2 | Upstream-Name: kubelet
3 | Source: https://github.com/kubernetes/kubernetes
4 |
5 | Files: *
6 | Copyright: 2016 The Kubernetes Authors.
7 | License: Apache-2.0
8 | Licensed under the Apache License, Version 2.0 (the "License");
9 | you may not use this file except in compliance with the License.
10 | You may obtain a copy of the License at
11 | .
12 | http://www.apache.org/licenses/LICENSE-2.0
13 | .
14 | Unless required by applicable law or agreed to in writing, software
15 | distributed under the License is distributed on an "AS IS" BASIS,
16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | See the License for the specific language governing permissions and
18 | limitations under the License.
19 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/kubelet.install:
--------------------------------------------------------------------------------
1 | usr/bin/kubelet usr/bin/
2 | lib/systemd/system/kubelet.service lib/systemd/system/
3 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/postinst:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # postinst script for kubelet
3 | #
4 | # see: dh_installdeb(1)
5 |
6 | set -o errexit
7 | set -o nounset
8 |
9 | # summary of how this script can be called:
10 | # * `configure'
11 | # * `abort-upgrade'
12 | # * `abort-remove' `in-favour'
13 | #
14 | # * `abort-remove'
15 | # * `abort-deconfigure' `in-favour'
16 | # `removing'
17 | #
18 | # for details, see https://www.debian.org/doc/debian-policy/ or
19 | # the debian-policy package
20 |
21 |
22 | case "$1" in
23 | configure)
24 | ;;
25 |
26 | abort-upgrade|abort-remove|abort-deconfigure)
27 | ;;
28 |
29 | *)
30 | echo "postinst called with unknown argument \`$1'" >&2
31 | exit 1
32 | ;;
33 | esac
34 |
35 | mkdir -p /etc/kubernetes/manifests
36 |
37 | # dh_installdeb will replace this with shell code automatically
38 | # generated by other debhelper scripts.
39 |
40 | #DEBHELPER#
41 |
42 | exit 0
43 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # -*- makefile -*-
3 |
4 | #export DH_VERBOSE=1
5 |
6 | build:
7 | echo noop
8 |
9 | binary:
10 | mkdir -p usr/bin
11 | cp kubelet usr/bin/kubelet
12 | chmod +x usr/bin/kubelet
13 | dh_testroot
14 | dh_auto_install
15 | dh_shlibdeps
16 | dh_install
17 | dh_systemd_enable
18 | dh_installinit
19 | dh_systemd_start
20 | dh_installdeb
21 | dh_gencontrol
22 | dh_md5sums
23 | dh_builddeb
24 |
25 | %:
26 | dh $@ --with systemd
27 |
--------------------------------------------------------------------------------
/deb/kubelet/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (native)
2 |
--------------------------------------------------------------------------------
/deb/kubelet/lib/systemd/system/kubelet.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=kubelet: The Kubernetes Node Agent
3 | Documentation=https://kubernetes.io/docs/home/
4 | Wants=network-online.target
5 | After=network-online.target
6 |
7 | [Service]
8 | ExecStart=/usr/bin/kubelet
9 | Restart=always
10 | StartLimitInterval=0
11 | RestartSec=10
12 |
13 | [Install]
14 | WantedBy=multi-user.target
15 |
--------------------------------------------------------------------------------
/hack/build_binaries.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | KUBE_BUILD_PLATFORMS=(
11 | linux/amd64
12 | linux/arm64
13 | )
14 | for platform in ${KUBE_BUILD_PLATFORMS[*]}; do
15 | ./build/run.sh make KUBE_BUILD_PLATFORMS="${platform}" kubectl kubelet kubeadm 2>&1 | grep -v -E '^I\w+ ' || echo "fail ${platform}"
16 | done
17 | TARGETS=$(ls _output/dockerized/bin/*/*/{kubectl,kubelet,kubeadm})
18 |
19 | rm -rf "${OUTPUT}"
20 | mkdir -p "${OUTPUT}"
21 | for target in $TARGETS; do
22 | dist=${target#_output/dockerized/bin/}
23 | mkdir -p "${OUTPUT}/${dist}"
24 | cp "${target}" "${OUTPUT}/${dist}/"
25 | done
26 |
--------------------------------------------------------------------------------
/hack/build_image.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | KUBE_DOCKER_REGISTRY=${KUBE_DOCKER_REGISTRY:-}
11 |
12 | KUBE_BUILD_PLATFORMS=(
13 | linux/amd64
14 | linux/arm64
15 | )
16 | for platform in ${KUBE_BUILD_PLATFORMS[*]}; do
17 | make KUBE_GIT_TREE_STATE=clean KUBE_BUILD_HYPERKUBE=n KUBE_BUILD_CONFORMANCE=n KUBE_BUILD_PULL_LATEST_IMAGES=n KUBE_RELEASE_RUN_TESTS=n KUBE_BUILD_PLATFORMS="${platform}" KUBE_DOCKER_REGISTRY="${KUBE_DOCKER_REGISTRY}" release-images || echo "fail ${platform}"
18 | done
19 |
--------------------------------------------------------------------------------
/hack/checkout.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | kit/checkout.sh $@
--------------------------------------------------------------------------------
/hack/format_all_patch.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | kit/format_all_patch.sh
8 |
--------------------------------------------------------------------------------
/hack/format_patch.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | kit/format_patch.sh $@
8 |
--------------------------------------------------------------------------------
/hack/gen_verify_workflows.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 |
9 | RELEASES=$(helper::config::list_releases)
10 |
11 | cat <&1 | grep -v -E '^I\w+ '
13 |
14 | IMAGE=$(KUBE_RUN_COPY_OUTPUT=n ./build/run.sh ./_output/bin/kubeadm config images list | grep -v '+++' | grep -v "/kube-" | sed -E 's/\s+/ /g' | sed 's/-amd64:/:/g')
15 |
16 | cd "${ROOT}"
17 | ./hack/image_manifest_retags.sh ${IMAGE}
18 |
--------------------------------------------------------------------------------
/hack/image_tag.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 |
8 | OLD_REGISTRY=${OLD_REGISTRY:-}
9 | REGISTRY=${REGISTRY:-}
10 | OLD_IMAGES=$(docker images | grep ${OLD_REGISTRY} | grep kube- | grep -v cross | awk '{print $1":"$2}')
11 | for old_image in ${OLD_IMAGES} ; do
12 | new_image=$(echo ${old_image} | sed "s#${OLD_REGISTRY}#${REGISTRY}#g")
13 | docker tag "${old_image}" "${new_image}"
14 | docker rmi "${old_image}"
15 | done
16 |
--------------------------------------------------------------------------------
/hack/install_etcd.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | hack/install-etcd.sh
11 | export PATH="${WORKDIR}/third_party/etcd:${PATH}"
12 |
13 | etcd --version
14 |
--------------------------------------------------------------------------------
/hack/kit.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | git clone --single-branch --depth 1 https://github.com/klts-io/kit
8 |
--------------------------------------------------------------------------------
/hack/pkg_deb.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | VERSION=$(helper::workdir::version)
11 | RELEASE="${VERSION##*-}"
12 | VERSION="${VERSION%-*}"
13 |
14 | if [[ "${VERSION}" == "${RELEASE}" ]]; then
15 | RELEASE="00"
16 | fi
17 |
18 | ${KITDIR}/pkg_deb.sh kubectl,kubelet,kubeadm amd64,arm64 "${VERSION}" "${RELEASE}"
19 |
--------------------------------------------------------------------------------
/hack/pkg_rpm.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | VERSION=$(helper::workdir::version)
11 | RELEASE="${VERSION##*-}"
12 | VERSION="${VERSION%-*}"
13 |
14 | if [[ "${VERSION}" == "${RELEASE}" ]]; then
15 | RELEASE="00"
16 | fi
17 |
18 | ${KITDIR}/pkg_rpm.sh kubectl,kubelet,kubeadm amd64,arm64 "${VERSION}" "${RELEASE}"
19 |
--------------------------------------------------------------------------------
/hack/public_source.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | kit/public_source.sh
8 |
--------------------------------------------------------------------------------
/hack/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | TMPFILE="${TMPDIR}/test.log"
11 |
12 | ./build/run.sh make test 2>&1 | tee "${TMPFILE}" | grep -v -E '^I\w+ ' && exit 0
13 |
14 | RETRY_CASES=$(cat "${TMPFILE}" | grep -E '^FAIL\s+k8s.io/kubernetes' | awk '{print $2}' || echo "")
15 |
16 | TAG=$(helper::workdir::version)
17 |
18 | FAILURES_TOLERATED=$(helper::config::get_test_failures_tolerated ${TAG})
19 | if [[ "${FAILURES_TOLERATED}" != "" ]]; then
20 | echo "+++ Test failed, the case is as follows:"
21 | echo "${RETRY_CASES}"
22 | echo "+++ Failures tolerated, the case is as follows:"
23 | echo "${FAILURES_TOLERATED}"
24 |
25 | for tolerate in ${FAILURES_TOLERATED}; do
26 | RETRY_CASES=$(echo "${RETRY_CASES}" | grep -v -E "^${tolerate}$" || echo "")
27 | done
28 | if [[ "${RETRY_CASES}" == "" ]]; then
29 | exit 0
30 | fi
31 | fi
32 |
33 | echo "+++ Test failed, will retry 5 times"
34 | for n in {1..5}; do
35 | echo "+++ Test retry ${n}, the case is as follows:"
36 | echo "${RETRY_CASES}"
37 | want=$(echo ${RETRY_CASES})
38 | ./build/run.sh make test WHAT="${want}" 2>&1 | tee "${TMPFILE}" | grep -v -E '^I\w+ ' && exit 0
39 | RETRY_CASES=$(cat "${TMPFILE}" | grep -E '^FAIL\s+k8s.io/kubernetes' | awk '{print $2}' || echo "")
40 | done
41 |
42 | echo "!!! Test failed, the case is as follows:"
43 | echo "${RETRY_CASES}"
44 |
45 | exit 1
46 |
--------------------------------------------------------------------------------
/hack/test_cmd.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | export KUBE_ROOT=$(dirname "$(readlink -f "$0")")/..
9 | export TERM=linux
10 | echo "KUBE_ROOT directory: $KUBE_ROOT"
11 | cd "${WORKDIR}"
12 |
13 | # Kubeadm was added for testing in 1.19 and later
14 | for n in {1..5}; do
15 | echo "+++ Test retry ${n}"
16 | ./build/shell.sh -c '
17 |
18 | # before v1.25
19 | make generated_files kubeadm
20 | # after v1.26
21 | ./build/run.sh make all WHAT=cmd/kubeadm
22 |
23 | mkdir -p _output/local/go/bin/ && cp _output/dockerized/bin/linux/amd64/kubeadm _output/local/go/bin/
24 | TERM=linux PATH=$(pwd)/third_party/etcd:${PATH} make test-cmd
25 | ' 2>&1 | grep -v -E '^I\w+ ' && exit 0
26 | done
27 |
--------------------------------------------------------------------------------
/hack/test_e2e.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | ./build/run.sh make test-e2e 2>&1 | grep -v -E '^I\w+ '
11 |
--------------------------------------------------------------------------------
/hack/test_e2e_node.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | ./build/run.sh make test-e2e-node 2>&1 | grep -v -E '^I\w+ '
11 |
--------------------------------------------------------------------------------
/hack/test_integration.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | export KUBE_ROOT=$(dirname "$(readlink -f "$0")")/..
9 | export TERM=linux
10 | echo "KUBE_ROOT directory: $KUBE_ROOT"
11 | cd "${WORKDIR}"
12 | echo "WORKDIR directory: $WORKDIR"
13 |
14 | TMPFILE="${TMPDIR}/test-integration.log"
15 |
16 | # Etcd was added for testing in 1.21 and later
17 | function test-integration() {
18 | ./build/shell.sh -c '
19 | # generate .make/go-pkgdeps.mk
20 | go install ./cmd/...
21 |
22 | # run test-integration
23 | KUBE_RUN_COPY_OUTPUT=y TERM=linux PATH=$(pwd)/third_party/etcd:${PATH} DBG_CODEGEN=1 make test-integration
24 | '
25 | }
26 |
27 | test-integration 2>&1 | tee "${TMPFILE}" | grep -v -E '^I\w+ ' && exit 0
28 |
29 | echo "-------print TMPFILE:"
30 | cat "${TMPFILE}"
31 | echo "-------TMPFILE end."
32 |
33 | RETRY_CASES=$(cat "${TMPFILE}" | grep -E '^FAIL\s+k8s.io/kubernetes' | awk '{print $2}' || echo "")
34 |
35 | TAG=$(helper::workdir::version)
36 |
37 | FAILURES_TOLERATED=$(helper::config::get_test_integration_failures_tolerated ${TAG})
38 | if [[ "${FAILURES_TOLERATED}" != "" ]]; then
39 | echo "+++ Test failed, the case is as follows:"
40 | echo "${RETRY_CASES}"
41 | echo "+++ Failures tolerated, the case is as follows:"
42 | echo "${FAILURES_TOLERATED}"
43 |
44 | for tolerate in ${FAILURES_TOLERATED}; do
45 | RETRY_CASES=$(echo "${RETRY_CASES}" | grep -v -E "^${tolerate}$" || echo "")
46 | done
47 | if [[ "${RETRY_CASES}" == "" ]]; then
48 | exit 0
49 | fi
50 | fi
51 |
52 | echo "+++ Test failed, will retry 5 times"
53 | for n in {1..5}; do
54 | echo "+++ Test retry ${n}, the case is as follows:"
55 | echo "${RETRY_CASES}"
56 | want=$(echo ${RETRY_CASES})
57 | test-integration WHAT="${want}" 2>&1 | tee "${TMPFILE}" | grep -v -E '^I\w+ ' && exit 0
58 | RETRY_CASES=$(cat "${TMPFILE}" | grep -E '^FAIL\s+k8s.io/kubernetes' | awk '{print $2}' || echo "")
59 | done
60 |
61 | echo "!!! Test failed, the case is as follows:"
62 | echo "${RETRY_CASES}"
63 |
64 | exit 1
65 |
--------------------------------------------------------------------------------
/hack/verify_build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | RELEASES=$(helper::config::list_releases)
11 |
12 | for release in ${RELEASES}; do
13 | echo "Verifying build release: ${release}"
14 | make "${release}" verify-build-client verify-build-server verify-build-image
15 | done
16 |
--------------------------------------------------------------------------------
/hack/verify_build_client.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | KUBE_BUILD_PLATFORMS=(
11 | linux/amd64
12 | )
13 |
14 | ./build/run.sh make KUBE_BUILD_PLATFORMS="${KUBE_BUILD_PLATFORMS}" kubectl 2>&1 | grep -v -E '^I\w+ ' || echo "client build failed"
15 |
16 | WANTS=(
17 | kubectl
18 | )
19 | TARGETS=$(ls _output/dockerized/bin/*/*/*)
20 | FAILD=false
21 | for want in ${WANTS}; do
22 | if ! [[ "${TARGETS}" =~ "${want}" ]]; then
23 | FAILD=true
24 | echo "Missing ${want}"
25 | fi
26 | done
27 |
28 | if [[ "${FAILD}" == true ]]; then
29 | exit 1
30 | fi
31 |
--------------------------------------------------------------------------------
/hack/verify_build_image.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | KUBE_BUILD_PLATFORMS=(
11 | linux/amd64
12 | )
13 |
14 | make KUBE_GIT_TREE_STATE=clean KUBE_BUILD_HYPERKUBE=n KUBE_BUILD_CONFORMANCE=n KUBE_BUILD_PULL_LATEST_IMAGES=n KUBE_RELEASE_RUN_TESTS=n KUBE_BUILD_PLATFORMS="${KUBE_BUILD_PLATFORMS}" release-images || echo "image build failed"
15 |
16 | WANTS=(
17 | kube-controller-manager
18 | kube-scheduler
19 | kube-apiserver
20 | kube-proxy
21 | )
22 | TARGETS=$(ls _output/release-images/*/*.tar)
23 | FAILD=false
24 | for want in ${WANTS}; do
25 | if ! [[ "${TARGETS}" =~ "${want}.tar" ]]; then
26 | FAILD=true
27 | echo "Missing ${want}.tar"
28 | fi
29 | done
30 |
31 | if [[ "${FAILD}" == true ]]; then
32 | exit 1
33 | fi
34 |
--------------------------------------------------------------------------------
/hack/verify_build_server.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${WORKDIR}"
9 |
10 | KUBE_BUILD_PLATFORMS=(
11 | linux/amd64
12 | )
13 |
14 | ./build/run.sh make KUBE_BUILD_PLATFORMS="${KUBE_BUILD_PLATFORMS}" kubelet kubeadm 2>&1 | grep -v -E '^I\w+ ' || echo "server build failed"
15 |
16 | WANTS=(
17 | kubelet
18 | kubeadm
19 | )
20 | TARGETS=$(ls _output/dockerized/bin/*/*/*)
21 | FAILD=false
22 | for want in ${WANTS}; do
23 | if ! [[ "${TARGETS}" =~ "${want}" ]]; then
24 | FAILD=true
25 | echo "Missing ${want}"
26 | fi
27 | done
28 |
29 | if [[ "${FAILD}" == true ]]; then
30 | exit 1
31 | fi
32 |
--------------------------------------------------------------------------------
/hack/verify_patch.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | RELEASES=$(helper::config::list_releases)
11 |
12 | make ${RELEASES}
13 |
--------------------------------------------------------------------------------
/hack/verify_patch_format.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | cp -r patches patches.bak
11 |
12 | function cleanup() {
13 | rm -rf patches.bak
14 | }
15 | trap cleanup EXIT
16 |
17 | ${KITDIR}/format_all_patch.sh
18 |
19 | diff -a patches patches.bak
20 |
--------------------------------------------------------------------------------
/hack/verify_pkg_deb_client.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | ./hack/pkg_deb.sh kubectl amd64
11 |
--------------------------------------------------------------------------------
/hack/verify_pkg_deb_server.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | ./hack/pkg_deb.sh kubeadm,kubelet amd64
11 |
--------------------------------------------------------------------------------
/hack/verify_pkg_rpm_client.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | ./hack/pkg_rpm.sh kubectl amd64
11 |
--------------------------------------------------------------------------------
/hack/verify_pkg_rpm_server.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 | set -o nounset
5 | set -o pipefail
6 |
7 | source "kit/helper.sh"
8 | cd "${ROOT}"
9 |
10 | ./hack/pkg_rpm.sh kubeadm,kubelet amd64
11 |
--------------------------------------------------------------------------------
/hack/verify_releases.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | LIST=$(cat releases.yml | yq -r '.releases | .[] | .name, .base_release' | xargs -n 2 )
4 |
5 |
6 | IFS=$'\n'
7 | for item in ${LIST} ; do
8 | name=$(echo ${item} | cut -d ' ' -f 1)
9 | base_release=$(echo ${item} | cut -d ' ' -f 2)
10 | if [[ "${name%%-*}" != "${base_release%%-*}" ]]; then
11 | echo "ERROR: ${name} is not a release of ${base_release}"
12 | exit 1
13 | fi
14 | done
15 |
--------------------------------------------------------------------------------
/patches/CVE-2019-1002101.1.10.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Maciej Szulik
3 | Date: Tue, 5 Mar 2019 14:55:01 +0100
4 | Subject: [PATCH] Fix panic in kubectl cp command
5 |
6 | ---
7 | pkg/kubectl/cmd/cp.go | 29 +++++++++++-
8 | pkg/kubectl/cmd/cp_test.go | 92 +++++++++++++++++++++++++++++++++-----
9 | 2 files changed, 107 insertions(+), 14 deletions(-)
10 |
11 | diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go
12 | index a438687ba3d..9b853a5ccaf 100644
13 | --- a/pkg/kubectl/cmd/cp.go
14 | +++ b/pkg/kubectl/cmd/cp.go
15 | @@ -244,6 +244,18 @@ func copyFromPod(f cmdutil.Factory, cmd *cobra.Command, cmderr io.Writer, src, d
16 | // stripPathShortcuts removes any leading or trailing "../" from a given path
17 | func stripPathShortcuts(p string) string {
18 | newPath := path.Clean(p)
19 | + trimmed := strings.TrimPrefix(newPath, "../")
20 | +
21 | + for trimmed != newPath {
22 | + newPath = trimmed
23 | + trimmed = strings.TrimPrefix(newPath, "../")
24 | + }
25 | +
26 | + // trim leftover {".", ".."}
27 | + if newPath == "." || newPath == ".." {
28 | + newPath = ""
29 | + }
30 | +
31 | if len(newPath) > 0 && string(newPath[0]) == "/" {
32 | return newPath[1:]
33 | }
34 | @@ -346,6 +358,12 @@ func untarAll(reader io.Reader, destFile, prefix string) error {
35 | }
36 | entrySeq++
37 | mode := header.FileInfo().Mode()
38 | + // all the files will start with the prefix, which is the directory where
39 | + // they were located on the pod, we need to strip down that prefix, but
40 | + // if the prefix is missing it means the tar was tempered with
41 | + if !strings.HasPrefix(header.Name, prefix) {
42 | + return fmt.Errorf("tar contents corrupted")
43 | + }
44 | outFileName := path.Join(destFile, clean(header.Name[len(prefix):]))
45 | baseName := path.Dir(outFileName)
46 | if err := os.MkdirAll(baseName, 0755); err != nil {
47 | @@ -370,8 +388,15 @@ func untarAll(reader io.Reader, destFile, prefix string) error {
48 | }
49 |
50 | if mode&os.ModeSymlink != 0 {
51 | - err := os.Symlink(header.Linkname, outFileName)
52 | - if err != nil {
53 | + linkname := header.Linkname
54 | + // error is returned if linkname can't be made relative to destFile,
55 | + // but relative can end up being ../dir that's why we also need to
56 | + // verify if relative path is the same after Clean-ing
57 | + relative, err := filepath.Rel(destFile, linkname)
58 | + if path.IsAbs(linkname) && (err != nil || relative != stripPathShortcuts(relative)) {
59 | + continue
60 | + }
61 | + if err := os.Symlink(linkname, outFileName); err != nil {
62 | return err
63 | }
64 | } else {
65 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
66 | index b7c0eb48722..7dabc93793e 100644
67 | --- a/pkg/kubectl/cmd/cp_test.go
68 | +++ b/pkg/kubectl/cmd/cp_test.go
69 | @@ -118,26 +118,32 @@ func TestGetPrefix(t *testing.T) {
70 | }
71 | }
72 |
73 | -func TestTarUntar(t *testing.T) {
74 | - dir, err := ioutil.TempDir("", "input")
75 | - dir2, err2 := ioutil.TempDir("", "output")
76 | - if err != nil || err2 != nil {
77 | - t.Errorf("unexpected error: %v | %v", err, err2)
78 | +func checkErr(t *testing.T, err error) {
79 | + if err != nil {
80 | + t.Errorf("unexpected error: %v", err)
81 | t.FailNow()
82 | }
83 | +}
84 | +
85 | +func TestTarUntar(t *testing.T) {
86 | + dir, err := ioutil.TempDir("", "input")
87 | + checkErr(t, err)
88 | + dir2, err := ioutil.TempDir("", "output")
89 | + checkErr(t, err)
90 | + dir3, err := ioutil.TempDir("", "dir")
91 | + checkErr(t, err)
92 | +
93 | dir = dir + "/"
94 | defer func() {
95 | - if err := os.RemoveAll(dir); err != nil {
96 | - t.Errorf("Unexpected error cleaning up: %v", err)
97 | - }
98 | - if err := os.RemoveAll(dir2); err != nil {
99 | - t.Errorf("Unexpected error cleaning up: %v", err)
100 | - }
101 | + os.RemoveAll(dir)
102 | + os.RemoveAll(dir2)
103 | + os.RemoveAll(dir3)
104 | }()
105 |
106 | files := []struct {
107 | name string
108 | data string
109 | + omitted bool
110 | fileType FileType
111 | }{
112 | {
113 | @@ -162,7 +168,24 @@ func TestTarUntar(t *testing.T) {
114 | },
115 | {
116 | name: "gakki",
117 | + data: "tmp/gakki",
118 | + fileType: SymLink,
119 | + },
120 | + {
121 | + name: "relative_to_dest",
122 | + data: path.Join(dir2, "foo"),
123 | + fileType: SymLink,
124 | + },
125 | + {
126 | + name: "tricky_relative",
127 | + data: path.Join(dir3, "xyz"),
128 | + omitted: true,
129 | + fileType: SymLink,
130 | + },
131 | + {
132 | + name: "absolute_path",
133 | data: "/tmp/gakki",
134 | + omitted: true,
135 | fileType: SymLink,
136 | },
137 | }
138 | @@ -228,7 +251,12 @@ func TestTarUntar(t *testing.T) {
139 | }
140 | } else if file.fileType == SymLink {
141 | dest, err := os.Readlink(filePath)
142 | -
143 | + if file.omitted {
144 | + if err != nil && strings.Contains(err.Error(), "no such file or directory") {
145 | + continue
146 | + }
147 | + t.Fatalf("expected to omit symlink for %s", filePath)
148 | + }
149 | if err != nil {
150 | t.Fatalf("unexpected error: %v", err)
151 | }
152 | @@ -242,6 +270,46 @@ func TestTarUntar(t *testing.T) {
153 | }
154 | }
155 |
156 | +func TestTarUntarWrongPrefix(t *testing.T) {
157 | + dir, err := ioutil.TempDir("", "input")
158 | + checkErr(t, err)
159 | + dir2, err := ioutil.TempDir("", "output")
160 | + checkErr(t, err)
161 | +
162 | + dir = dir + "/"
163 | + defer func() {
164 | + os.RemoveAll(dir)
165 | + os.RemoveAll(dir2)
166 | + }()
167 | +
168 | + filepath := path.Join(dir, "foo")
169 | + if err := os.MkdirAll(path.Dir(filepath), 0755); err != nil {
170 | + t.Fatalf("unexpected error: %v", err)
171 | + }
172 | + f, err := os.Create(filepath)
173 | + if err != nil {
174 | + t.Fatalf("unexpected error: %v", err)
175 | + }
176 | + defer f.Close()
177 | + if _, err := io.Copy(f, bytes.NewBuffer([]byte("sample data"))); err != nil {
178 | + t.Fatalf("unexpected error: %v", err)
179 | + }
180 | + if err := f.Close(); err != nil {
181 | + t.Fatal(err)
182 | + }
183 | +
184 | + writer := &bytes.Buffer{}
185 | + if err := makeTar(dir, dir, writer); err != nil {
186 | + t.Fatalf("unexpected error: %v", err)
187 | + }
188 | +
189 | + reader := bytes.NewBuffer(writer.Bytes())
190 | + err = untarAll(reader, dir2, "verylongprefix-showing-the-tar-was-tempered-with")
191 | + if err == nil || !strings.Contains(err.Error(), "tar contents corrupted") {
192 | + t.Fatalf("unexpected error: %v", err)
193 | + }
194 | +}
195 | +
196 | // TestCopyToLocalFileOrDir tests untarAll in two cases :
197 | // 1: copy pod file to local file
198 | // 2: copy pod file into local directory
199 |
--------------------------------------------------------------------------------
/patches/CVE-2019-11246.1.10.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Tim Allclair
3 | Date: Fri, 12 Apr 2019 18:37:53 -0700
4 | Subject: [PATCH 1/2] Test kubectl cp escape
5 |
6 | ---
7 | pkg/kubectl/cmd/cp_test.go | 189 +++++++++++++++++++++++++++++++++++++
8 | 1 file changed, 189 insertions(+)
9 |
10 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
11 | index 7dabc93793e..51b356a7eba 100644
12 | --- a/pkg/kubectl/cmd/cp_test.go
13 | +++ b/pkg/kubectl/cmd/cp_test.go
14 | @@ -29,6 +29,7 @@ import (
15 | "strings"
16 | "testing"
17 |
18 | + "github.com/stretchr/testify/require"
19 | "k8s.io/api/core/v1"
20 | "k8s.io/apimachinery/pkg/api/errors"
21 | "k8s.io/apimachinery/pkg/runtime"
22 | @@ -644,3 +645,191 @@ func TestCopyToPod(t *testing.T) {
23 | })
24 | }
25 | }
26 | +
27 | +func TestUntar(t *testing.T) {
28 | + testdir, err := ioutil.TempDir("", "test-untar")
29 | + require.NoError(t, err)
30 | + defer os.RemoveAll(testdir)
31 | + t.Logf("Test base: %s", testdir)
32 | +
33 | + const (
34 | + dest = "base"
35 | + )
36 | +
37 | + type file struct {
38 | + path string
39 | + linkTarget string // For link types
40 | + expected string // Expect to find the file here (or not, if empty)
41 | + }
42 | + files := []file{{
43 | + // Absolute file within dest
44 | + path: filepath.Join(testdir, dest, "abs"),
45 | + expected: filepath.Join(testdir, dest, testdir, dest, "abs"),
46 | + }, { // Absolute file outside dest
47 | + path: filepath.Join(testdir, "abs-out"),
48 | + expected: filepath.Join(testdir, dest, testdir, "abs-out"),
49 | + }, { // Absolute nested file within dest
50 | + path: filepath.Join(testdir, dest, "nested/nest-abs"),
51 | + expected: filepath.Join(testdir, dest, testdir, dest, "nested/nest-abs"),
52 | + }, { // Absolute nested file outside dest
53 | + path: filepath.Join(testdir, dest, "nested/../../nest-abs-out"),
54 | + expected: filepath.Join(testdir, dest, testdir, "nest-abs-out"),
55 | + }, { // Relative file inside dest
56 | + path: "relative",
57 | + expected: filepath.Join(testdir, dest, "relative"),
58 | + }, { // Relative file outside dest
59 | + path: "../unrelative",
60 | + expected: filepath.Join(testdir, dest, "unrelative"),
61 | + }, { // Nested relative file inside dest
62 | + path: "nested/nest-rel",
63 | + expected: filepath.Join(testdir, dest, "nested/nest-rel"),
64 | + }, { // Nested relative file outside dest
65 | + path: "nested/../../nest-unrelative",
66 | + expected: filepath.Join(testdir, dest, "nest-unrelative"),
67 | + }}
68 | +
69 | + mkExpectation := func(expected, suffix string) string {
70 | + if expected == "" {
71 | + return ""
72 | + }
73 | + return expected + suffix
74 | + }
75 | + links := []file{}
76 | + for _, f := range files {
77 | + links = append(links, file{
78 | + path: f.path + "-innerlink",
79 | + linkTarget: "link-target",
80 | + expected: mkExpectation(f.expected, "-innerlink"),
81 | + }, file{
82 | + path: f.path + "-innerlink-abs",
83 | + linkTarget: filepath.Join(testdir, dest, "link-target"),
84 | + expected: "",
85 | + }, file{
86 | + path: f.path + "-outerlink",
87 | + linkTarget: filepath.Join(backtick(f.path), "link-target"),
88 | + expected: "",
89 | + }, file{
90 | + path: f.path + "-outerlink-abs",
91 | + linkTarget: filepath.Join(testdir, "link-target"),
92 | + expected: "",
93 | + })
94 | + }
95 | + files = append(files, links...)
96 | +
97 | + // Test back-tick escaping through a symlink.
98 | + files = append(files,
99 | + file{
100 | + path: "nested/again/back-link",
101 | + linkTarget: "../../nested",
102 | + expected: filepath.Join(testdir, dest, "nested/again/back-link"),
103 | + },
104 | + file{
105 | + path: "nested/again/back-link/../../../back-link-file",
106 | + expected: filepath.Join(testdir, dest, "back-link-file"),
107 | + })
108 | +
109 | + // Test chaining back-tick symlinks.
110 | + files = append(files,
111 | + file{
112 | + path: "nested/back-link-first",
113 | + linkTarget: "../",
114 | + expected: filepath.Join(testdir, dest, "nested/back-link-first"),
115 | + },
116 | + file{
117 | + path: "nested/back-link-first/back-link-second",
118 | + linkTarget: "../",
119 | + expected: filepath.Join(testdir, dest, "back-link-second"),
120 | + },
121 | + file{
122 | + path: "nested/back-link-first/back-link-second/back-link-term",
123 | + })
124 | +
125 | + buf := &bytes.Buffer{}
126 | + tw := tar.NewWriter(buf)
127 | + expectations := map[string]bool{}
128 | + for _, f := range files {
129 | + if f.expected != "" {
130 | + expectations[f.expected] = false
131 | + }
132 | + if f.linkTarget == "" {
133 | + hdr := &tar.Header{
134 | + Name: f.path,
135 | + Mode: 0666,
136 | + Size: int64(len(f.path)),
137 | + }
138 | + require.NoError(t, tw.WriteHeader(hdr), f.path)
139 | + _, err := tw.Write([]byte(f.path))
140 | + require.NoError(t, err, f.path)
141 | + } else {
142 | + hdr := &tar.Header{
143 | + Name: f.path,
144 | + Mode: int64(0777 | os.ModeSymlink),
145 | + Typeflag: tar.TypeSymlink,
146 | + Linkname: f.linkTarget,
147 | + }
148 | + require.NoError(t, tw.WriteHeader(hdr), f.path)
149 | + }
150 | + }
151 | + tw.Close()
152 | +
153 | + require.NoError(t, untarAll(buf, filepath.Join(testdir, dest), ""))
154 | +
155 | + filepath.Walk(testdir, func(path string, info os.FileInfo, err error) error {
156 | + if err != nil {
157 | + return err
158 | + }
159 | + if info.IsDir() {
160 | + return nil // Ignore directories.
161 | + }
162 | + if _, ok := expectations[path]; !ok {
163 | + t.Errorf("Unexpected file at %s", path)
164 | + } else {
165 | + expectations[path] = true
166 | + }
167 | + return nil
168 | + })
169 | + for path, found := range expectations {
170 | + if !found {
171 | + t.Errorf("Missing expected file %s", path)
172 | + }
173 | + }
174 | +}
175 | +
176 | +// backtick returns a path to one directory up from the target
177 | +func backtick(target string) string {
178 | + rel, _ := filepath.Rel(filepath.Dir(target), "../")
179 | + return rel
180 | +}
181 | +
182 | +func createTmpFile(t *testing.T, filepath, data string) {
183 | + f, err := os.Create(filepath)
184 | + if err != nil {
185 | + t.Fatalf("unexpected error: %v", err)
186 | + }
187 | + defer f.Close()
188 | + if _, err := io.Copy(f, bytes.NewBuffer([]byte(data))); err != nil {
189 | + t.Fatalf("unexpected error: %v", err)
190 | + }
191 | + if err := f.Close(); err != nil {
192 | + t.Fatal(err)
193 | + }
194 | +}
195 | +
196 | +func cmpFileData(t *testing.T, filePath, data string) {
197 | + f, err := os.Open(filePath)
198 | + if err != nil {
199 | + t.Fatalf("unexpected error: %v", err)
200 | + }
201 | +
202 | + defer f.Close()
203 | + buff := &bytes.Buffer{}
204 | + if _, err := io.Copy(buff, f); err != nil {
205 | + t.Fatal(err)
206 | + }
207 | + if err := f.Close(); err != nil {
208 | + t.Fatal(err)
209 | + }
210 | + if data != string(buff.Bytes()) {
211 | + t.Fatalf("expected: %s, saw: %s", data, string(buff.Bytes()))
212 | + }
213 | +}
214 |
215 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
216 | From: Maciej Szulik
217 | Date: Tue, 16 Apr 2019 15:49:16 +0200
218 | Subject: [PATCH 2/2] Properly handle links in tar
219 |
220 | ---
221 | pkg/kubectl/cmd/BUILD | 1 +
222 | pkg/kubectl/cmd/cp.go | 99 +++++++++++++----------
223 | pkg/kubectl/cmd/cp_test.go | 159 +++++++++++++++++++++++++++++++++++--
224 | 3 files changed, 208 insertions(+), 51 deletions(-)
225 |
226 | diff --git a/pkg/kubectl/cmd/BUILD b/pkg/kubectl/cmd/BUILD
227 | index 45707367c48..e72ba1a7566 100644
228 | --- a/pkg/kubectl/cmd/BUILD
229 | +++ b/pkg/kubectl/cmd/BUILD
230 | @@ -233,6 +233,7 @@ go_test(
231 | "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
232 | "//vendor/github.com/spf13/cobra:go_default_library",
233 | "//vendor/github.com/stretchr/testify/assert:go_default_library",
234 | + "//vendor/github.com/stretchr/testify/require:go_default_library",
235 | "//vendor/gopkg.in/yaml.v2:go_default_library",
236 | "//vendor/k8s.io/api/batch/v1:go_default_library",
237 | "//vendor/k8s.io/api/batch/v1beta1:go_default_library",
238 | diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go
239 | index 9b853a5ccaf..d406d52cf0d 100644
240 | --- a/pkg/kubectl/cmd/cp.go
241 | +++ b/pkg/kubectl/cmd/cp.go
242 | @@ -343,9 +343,7 @@ func clean(fileName string) string {
243 | return path.Clean(string(os.PathSeparator) + fileName)
244 | }
245 |
246 | -func untarAll(reader io.Reader, destFile, prefix string) error {
247 | - entrySeq := -1
248 | -
249 | +func untarAll(reader io.Reader, destDir, prefix string) error {
250 | // TODO: use compression here?
251 | tarReader := tar.NewReader(reader)
252 | for {
253 | @@ -356,51 +354,60 @@ func untarAll(reader io.Reader, destFile, prefix string) error {
254 | }
255 | break
256 | }
257 | - entrySeq++
258 | - mode := header.FileInfo().Mode()
259 | - // all the files will start with the prefix, which is the directory where
260 | +
261 | + // All the files will start with the prefix, which is the directory where
262 | // they were located on the pod, we need to strip down that prefix, but
263 | - // if the prefix is missing it means the tar was tempered with
264 | + // if the prefix is missing it means the tar was tempered with.
265 | + // For the case where prefix is empty we need to ensure that the path
266 | + // is not absolute, which also indicates the tar file was tempered with.
267 | if !strings.HasPrefix(header.Name, prefix) {
268 | return fmt.Errorf("tar contents corrupted")
269 | }
270 | - outFileName := path.Join(destFile, clean(header.Name[len(prefix):]))
271 | - baseName := path.Dir(outFileName)
272 | +
273 | + // basic file information
274 | + mode := header.FileInfo().Mode()
275 | + destFileName := path.Join(destDir, header.Name[len(prefix):])
276 | + baseName := path.Dir(destFileName)
277 | +
278 | if err := os.MkdirAll(baseName, 0755); err != nil {
279 | return err
280 | }
281 | if header.FileInfo().IsDir() {
282 | - if err := os.MkdirAll(outFileName, 0755); err != nil {
283 | + if err := os.MkdirAll(destFileName, 0755); err != nil {
284 | return err
285 | }
286 | continue
287 | }
288 |
289 | - // handle coping remote file into local directory
290 | - if entrySeq == 0 && !header.FileInfo().IsDir() {
291 | - exists, err := dirExists(outFileName)
292 | - if err != nil {
293 | - return err
294 | - }
295 | - if exists {
296 | - outFileName = filepath.Join(outFileName, path.Base(clean(header.Name)))
297 | - }
298 | + // We need to ensure that the destination file is always within boundries
299 | + // of the destination directory. This prevents any kind of path traversal
300 | + // from within tar archive.
301 | + dir, file := filepath.Split(destFileName)
302 | + evaledPath, err := filepath.EvalSymlinks(dir)
303 | + if err != nil {
304 | + return err
305 | + }
306 | + // For scrutiny we verify both the actual destination as well as we follow
307 | + // all the links that might lead outside of the destination directory.
308 | + if !isDestRelative(destDir, destFileName) || !isDestRelative(destDir, filepath.Join(evaledPath, file)) {
309 | + fmt.Fprintf(os.Stderr, "warning: link %q is pointing to %q which is outside target destination, skipping\n", destFileName, header.Linkname)
310 | + continue
311 | }
312 |
313 | if mode&os.ModeSymlink != 0 {
314 | linkname := header.Linkname
315 | - // error is returned if linkname can't be made relative to destFile,
316 | - // but relative can end up being ../dir that's why we also need to
317 | - // verify if relative path is the same after Clean-ing
318 | - relative, err := filepath.Rel(destFile, linkname)
319 | - if path.IsAbs(linkname) && (err != nil || relative != stripPathShortcuts(relative)) {
320 | + // We need to ensure that the link destination is always within boundries
321 | + // of the destination directory. This prevents any kind of path traversal
322 | + // from within tar archive.
323 | + if !isDestRelative(destDir, linkJoin(destFileName, linkname)) {
324 | + fmt.Fprintf(os.Stderr, "warning: link %q is pointing to %q which is outside target destination, skipping\n", destFileName, header.Linkname)
325 | continue
326 | }
327 | - if err := os.Symlink(linkname, outFileName); err != nil {
328 | + if err := os.Symlink(linkname, destFileName); err != nil {
329 | return err
330 | }
331 | } else {
332 | - outFile, err := os.Create(outFileName)
333 | + outFile, err := os.Create(destFileName)
334 | if err != nil {
335 | return err
336 | }
337 | @@ -414,14 +421,32 @@ func untarAll(reader io.Reader, destFile, prefix string) error {
338 | }
339 | }
340 |
341 | - if entrySeq == -1 {
342 | - //if no file was copied
343 | - errInfo := fmt.Sprintf("error: %s no such file or directory", prefix)
344 | - return errors.New(errInfo)
345 | - }
346 | return nil
347 | }
348 |
349 | +// linkJoin joins base and link to get the final path to be created.
350 | +// It will consider whether link is an absolute path or not when returning result.
351 | +func linkJoin(base, link string) string {
352 | + if filepath.IsAbs(link) {
353 | + return link
354 | + }
355 | + return filepath.Join(base, link)
356 | +}
357 | +
358 | +// isDestRelative returns true if dest is pointing outside the base directory,
359 | +// false otherwise.
360 | +func isDestRelative(base, dest string) bool {
361 | + fullPath := dest
362 | + if !filepath.IsAbs(dest) {
363 | + fullPath = filepath.Join(base, dest)
364 | + }
365 | + relative, err := filepath.Rel(base, fullPath)
366 | + if err != nil {
367 | + return false
368 | + }
369 | + return relative == "." || relative == stripPathShortcuts(relative)
370 | +}
371 | +
372 | func getPrefix(file string) string {
373 | // tar strips the leading '/' if it's there, so we will too
374 | return strings.TrimLeft(file, "/")
375 | @@ -462,15 +487,3 @@ func execute(f cmdutil.Factory, cmd *cobra.Command, options *ExecOptions) error
376 | }
377 | return nil
378 | }
379 | -
380 | -// dirExists checks if a path exists and is a directory.
381 | -func dirExists(path string) (bool, error) {
382 | - fi, err := os.Stat(path)
383 | - if err == nil && fi.IsDir() {
384 | - return true, nil
385 | - }
386 | - if os.IsNotExist(err) {
387 | - return false, nil
388 | - }
389 | - return false, err
390 | -}
391 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
392 | index 51b356a7eba..5e5c3e6b72e 100644
393 | --- a/pkg/kubectl/cmd/cp_test.go
394 | +++ b/pkg/kubectl/cmd/cp_test.go
395 | @@ -19,6 +19,7 @@ package cmd
396 | import (
397 | "archive/tar"
398 | "bytes"
399 | + "fmt"
400 | "io"
401 | "io/ioutil"
402 | "net/http"
403 | @@ -119,6 +120,128 @@ func TestGetPrefix(t *testing.T) {
404 | }
405 | }
406 |
407 | +func TestStripPathShortcuts(t *testing.T) {
408 | + tests := []struct {
409 | + name string
410 | + input string
411 | + expected string
412 | + }{
413 | + {
414 | + name: "test single path shortcut prefix",
415 | + input: "../foo/bar",
416 | + expected: "foo/bar",
417 | + },
418 | + {
419 | + name: "test multiple path shortcuts",
420 | + input: "../../foo/bar",
421 | + expected: "foo/bar",
422 | + },
423 | + {
424 | + name: "test multiple path shortcuts with absolute path",
425 | + input: "/tmp/one/two/../../foo/bar",
426 | + expected: "tmp/foo/bar",
427 | + },
428 | + {
429 | + name: "test multiple path shortcuts with no named directory",
430 | + input: "../../",
431 | + expected: "",
432 | + },
433 | + {
434 | + name: "test multiple path shortcuts with no named directory and no trailing slash",
435 | + input: "../..",
436 | + expected: "",
437 | + },
438 | + {
439 | + name: "test multiple path shortcuts with absolute path and filename containing leading dots",
440 | + input: "/tmp/one/two/../../foo/..bar",
441 | + expected: "tmp/foo/..bar",
442 | + },
443 | + {
444 | + name: "test multiple path shortcuts with no named directory and filename containing leading dots",
445 | + input: "../...foo",
446 | + expected: "...foo",
447 | + },
448 | + {
449 | + name: "test filename containing leading dots",
450 | + input: "...foo",
451 | + expected: "...foo",
452 | + },
453 | + {
454 | + name: "test root directory",
455 | + input: "/",
456 | + expected: "",
457 | + },
458 | + }
459 | +
460 | + for _, test := range tests {
461 | + out := stripPathShortcuts(test.input)
462 | + if out != test.expected {
463 | + t.Errorf("expected: %s, saw: %s", test.expected, out)
464 | + }
465 | + }
466 | +}
467 | +func TestIsDestRelative(t *testing.T) {
468 | + tests := []struct {
469 | + base string
470 | + dest string
471 | + relative bool
472 | + }{
473 | + {
474 | + base: "/dir",
475 | + dest: "../link",
476 | + relative: false,
477 | + },
478 | + {
479 | + base: "/dir",
480 | + dest: "../../link",
481 | + relative: false,
482 | + },
483 | + {
484 | + base: "/dir",
485 | + dest: "/link",
486 | + relative: false,
487 | + },
488 | + {
489 | + base: "/dir",
490 | + dest: "link",
491 | + relative: true,
492 | + },
493 | + {
494 | + base: "/dir",
495 | + dest: "int/file/link",
496 | + relative: true,
497 | + },
498 | + {
499 | + base: "/dir",
500 | + dest: "int/../link",
501 | + relative: true,
502 | + },
503 | + {
504 | + base: "/dir",
505 | + dest: "/dir/link",
506 | + relative: true,
507 | + },
508 | + {
509 | + base: "/dir",
510 | + dest: "/dir/int/../link",
511 | + relative: true,
512 | + },
513 | + {
514 | + base: "/dir",
515 | + dest: "/dir/../../link",
516 | + relative: false,
517 | + },
518 | + }
519 | +
520 | + for i, test := range tests {
521 | + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
522 | + if test.relative != isDestRelative(test.base, test.dest) {
523 | + t.Errorf("unexpected result for: base %q, dest %q", test.base, test.dest)
524 | + }
525 | + })
526 | + }
527 | +}
528 | +
529 | func checkErr(t *testing.T, err error) {
530 | if err != nil {
531 | t.Errorf("unexpected error: %v", err)
532 | @@ -517,7 +640,6 @@ func TestBadTar(t *testing.T) {
533 | name string
534 | body string
535 | }{
536 | - {"/prefix/../../../tmp/foo", "Up to temp"},
537 | {"/prefix/foo/bar/../../home/bburns/names.txt", "Down and back"},
538 | }
539 | for _, file := range files {
540 | @@ -679,13 +801,13 @@ func TestUntar(t *testing.T) {
541 | expected: filepath.Join(testdir, dest, "relative"),
542 | }, { // Relative file outside dest
543 | path: "../unrelative",
544 | - expected: filepath.Join(testdir, dest, "unrelative"),
545 | + expected: "",
546 | }, { // Nested relative file inside dest
547 | path: "nested/nest-rel",
548 | expected: filepath.Join(testdir, dest, "nested/nest-rel"),
549 | }, { // Nested relative file outside dest
550 | path: "nested/../../nest-unrelative",
551 | - expected: filepath.Join(testdir, dest, "nest-unrelative"),
552 | + expected: "",
553 | }}
554 |
555 | mkExpectation := func(expected, suffix string) string {
556 | @@ -694,6 +816,13 @@ func TestUntar(t *testing.T) {
557 | }
558 | return expected + suffix
559 | }
560 | + mkBacktickExpectation := func(expected, suffix string) string {
561 | + dir, _ := filepath.Split(filepath.Clean(expected))
562 | + if len(strings.Split(dir, string(os.PathSeparator))) <= 1 {
563 | + return ""
564 | + }
565 | + return expected + suffix
566 | + }
567 | links := []file{}
568 | for _, f := range files {
569 | links = append(links, file{
570 | @@ -703,11 +832,11 @@ func TestUntar(t *testing.T) {
571 | }, file{
572 | path: f.path + "-innerlink-abs",
573 | linkTarget: filepath.Join(testdir, dest, "link-target"),
574 | - expected: "",
575 | + expected: mkExpectation(f.expected, "-innerlink-abs"),
576 | }, file{
577 | path: f.path + "-outerlink",
578 | linkTarget: filepath.Join(backtick(f.path), "link-target"),
579 | - expected: "",
580 | + expected: mkBacktickExpectation(f.expected, "-outerlink"),
581 | }, file{
582 | path: f.path + "-outerlink-abs",
583 | linkTarget: filepath.Join(testdir, "link-target"),
584 | @@ -741,7 +870,19 @@ func TestUntar(t *testing.T) {
585 | expected: filepath.Join(testdir, dest, "back-link-second"),
586 | },
587 | file{
588 | - path: "nested/back-link-first/back-link-second/back-link-term",
589 | + // This case is chaining together symlinks that step back, so that
590 | + // if you just look at the target relative to the path it appears
591 | + // inside the destination directory, but if you actually follow each
592 | + // step of the path you end up outside the destination directory.
593 | + path: "nested/back-link-first/back-link-second/back-link-term",
594 | + linkTarget: "",
595 | + expected: "",
596 | + })
597 | +
598 | + files = append(files,
599 | + file{ // Relative directory path with terminating /
600 | + path: "direct/dir/",
601 | + expected: "",
602 | })
603 |
604 | buf := &bytes.Buffer{}
605 | @@ -758,8 +899,10 @@ func TestUntar(t *testing.T) {
606 | Size: int64(len(f.path)),
607 | }
608 | require.NoError(t, tw.WriteHeader(hdr), f.path)
609 | - _, err := tw.Write([]byte(f.path))
610 | - require.NoError(t, err, f.path)
611 | + if !strings.HasSuffix(f.path, "/") {
612 | + _, err := tw.Write([]byte(f.path))
613 | + require.NoError(t, err, f.path)
614 | + }
615 | } else {
616 | hdr := &tar.Header{
617 | Name: f.path,
618 |
--------------------------------------------------------------------------------
/patches/CVE-2019-11247.1.11.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: "Dr. Stefan Schimanski"
3 | Date: Mon, 1 Jul 2019 21:24:02 +0200
4 | Subject: [PATCH] apiextensions: 404 if request scope does not match crd scope
5 |
6 | ---
7 | .../pkg/apiserver/customresource_handler.go | 19 +++++++++++++++++++
8 | 1 file changed, 19 insertions(+)
9 |
10 | diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go
11 | index 7be3711dc17..63cd6a90fc3 100644
12 | --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go
13 | +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go
14 | @@ -43,6 +43,7 @@ import (
15 | "k8s.io/apimachinery/pkg/runtime/serializer/versioning"
16 | "k8s.io/apimachinery/pkg/types"
17 | utilruntime "k8s.io/apimachinery/pkg/util/runtime"
18 | + "k8s.io/apimachinery/pkg/util/sets"
19 | "k8s.io/apiserver/pkg/admission"
20 | "k8s.io/apiserver/pkg/endpoints/handlers"
21 | "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
22 | @@ -153,6 +154,10 @@ func NewCustomResourceDefinitionHandler(
23 | return ret
24 | }
25 |
26 | +// possiblyAcrossAllNamespacesVerbs contains those verbs which can be per-namespace and across all
27 | +// namespaces for namespaces resources. I.e. for these an empty namespace in the requestInfo is fine.
28 | +var possiblyAcrossAllNamespacesVerbs = sets.NewString("list", "watch")
29 | +
30 | func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
31 | ctx := req.Context()
32 | requestInfo, ok := apirequest.RequestInfoFrom(ctx)
33 | @@ -188,10 +193,24 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
34 | http.Error(w, err.Error(), http.StatusInternalServerError)
35 | return
36 | }
37 | +
38 | + // if the scope in the CRD and the scope in request differ (with exception of the verbs in possiblyAcrossAllNamespacesVerbs
39 | + // for namespaced resources), pass request to the delegate, which is supposed to lead to a 404.
40 | + namespacedCRD, namespacedReq := crd.Spec.Scope == apiextensions.NamespaceScoped, len(requestInfo.Namespace) > 0
41 | + if !namespacedCRD && namespacedReq {
42 | + r.delegate.ServeHTTP(w, req)
43 | + return
44 | + }
45 | + if namespacedCRD && !namespacedReq && !possiblyAcrossAllNamespacesVerbs.Has(requestInfo.Verb) {
46 | + r.delegate.ServeHTTP(w, req)
47 | + return
48 | + }
49 | +
50 | if !apiextensions.HasServedCRDVersion(crd, requestInfo.APIVersion) {
51 | r.delegate.ServeHTTP(w, req)
52 | return
53 | }
54 | +
55 | // There is a small chance that a CRD is being served because NamesAccepted condition is true,
56 | // but it becomes "unserved" because another names update leads to a conflict
57 | // and EstablishingController wasn't fast enough to put the CRD into the Established condition.
58 |
--------------------------------------------------------------------------------
/patches/CVE-2019-11248.1.11.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Tim Allclair
3 | Date: Thu, 16 May 2019 17:31:16 -0700
4 | Subject: [PATCH] Avoid the default server mux
5 |
6 | ---
7 | cmd/kubelet/app/server.go | 5 +++--
8 | staging/src/k8s.io/apiserver/pkg/server/healthz/doc.go | 2 +-
9 | .../src/k8s.io/apiserver/pkg/server/healthz/healthz.go | 10 ----------
10 | 3 files changed, 4 insertions(+), 13 deletions(-)
11 |
12 | diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go
13 | index bcd5ea562ae..ab816ae2d88 100644
14 | --- a/cmd/kubelet/app/server.go
15 | +++ b/cmd/kubelet/app/server.go
16 | @@ -726,9 +726,10 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan
17 | }
18 |
19 | if s.HealthzPort > 0 {
20 | - healthz.DefaultHealthz()
21 | + mux := http.NewServeMux()
22 | + healthz.InstallHandler(mux)
23 | go wait.Until(func() {
24 | - err := http.ListenAndServe(net.JoinHostPort(s.HealthzBindAddress, strconv.Itoa(int(s.HealthzPort))), nil)
25 | + err := http.ListenAndServe(net.JoinHostPort(s.HealthzBindAddress, strconv.Itoa(int(s.HealthzPort))), mux)
26 | if err != nil {
27 | glog.Errorf("Starting health server failed: %v", err)
28 | }
29 | diff --git a/staging/src/k8s.io/apiserver/pkg/server/healthz/doc.go b/staging/src/k8s.io/apiserver/pkg/server/healthz/doc.go
30 | index 06e67f6fe3c..d938caa3713 100644
31 | --- a/staging/src/k8s.io/apiserver/pkg/server/healthz/doc.go
32 | +++ b/staging/src/k8s.io/apiserver/pkg/server/healthz/doc.go
33 | @@ -17,5 +17,5 @@ limitations under the License.
34 | // Package healthz implements basic http server health checking.
35 | // Usage:
36 | // import "k8s.io/apiserver/pkg/server/healthz"
37 | -// healthz.DefaultHealthz()
38 | +// healthz.InstallHandler(mux)
39 | package healthz // import "k8s.io/apiserver/pkg/server/healthz"
40 | diff --git a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go
41 | index 991618238ea..aa5c77559bd 100644
42 | --- a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go
43 | +++ b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go
44 | @@ -21,7 +21,6 @@ import (
45 | "fmt"
46 | "net/http"
47 | "strings"
48 | - "sync"
49 |
50 | "github.com/golang/glog"
51 |
52 | @@ -34,15 +33,6 @@ type HealthzChecker interface {
53 | Check(req *http.Request) error
54 | }
55 |
56 | -var defaultHealthz = sync.Once{}
57 | -
58 | -// DefaultHealthz installs the default healthz check to the http.DefaultServeMux.
59 | -func DefaultHealthz(checks ...HealthzChecker) {
60 | - defaultHealthz.Do(func() {
61 | - InstallHandler(http.DefaultServeMux, checks...)
62 | - })
63 | -}
64 | -
65 | // PingHealthz returns true automatically when checked
66 | var PingHealthz HealthzChecker = ping{}
67 |
68 |
--------------------------------------------------------------------------------
/patches/CVE-2019-11249.1.10.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: M00nF1sh
3 | Date: Mon, 24 Jun 2019 11:16:00 -0700
4 | Subject: [PATCH 1/2] refactors to kubernetes CP command
5 |
6 | ---
7 | pkg/kubectl/cmd/cp.go | 5 +----
8 | pkg/kubectl/cmd/cp_test.go | 36 ++++++++++++++++--------------------
9 | 2 files changed, 17 insertions(+), 24 deletions(-)
10 |
11 | diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go
12 | index d406d52cf0d..18a5c0176bc 100644
13 | --- a/pkg/kubectl/cmd/cp.go
14 | +++ b/pkg/kubectl/cmd/cp.go
15 | @@ -430,16 +430,13 @@ func linkJoin(base, link string) string {
16 | if filepath.IsAbs(link) {
17 | return link
18 | }
19 | - return filepath.Join(base, link)
20 | + return filepath.Join(filepath.Dir(base), link)
21 | }
22 |
23 | // isDestRelative returns true if dest is pointing outside the base directory,
24 | // false otherwise.
25 | func isDestRelative(base, dest string) bool {
26 | fullPath := dest
27 | - if !filepath.IsAbs(dest) {
28 | - fullPath = filepath.Join(base, dest)
29 | - }
30 | relative, err := filepath.Rel(base, fullPath)
31 | if err != nil {
32 | return false
33 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
34 | index 5e5c3e6b72e..7b58cd92f4b 100644
35 | --- a/pkg/kubectl/cmd/cp_test.go
36 | +++ b/pkg/kubectl/cmd/cp_test.go
37 | @@ -188,12 +188,12 @@ func TestIsDestRelative(t *testing.T) {
38 | }{
39 | {
40 | base: "/dir",
41 | - dest: "../link",
42 | + dest: "/dir/../link",
43 | relative: false,
44 | },
45 | {
46 | base: "/dir",
47 | - dest: "../../link",
48 | + dest: "/dir/../../link",
49 | relative: false,
50 | },
51 | {
52 | @@ -203,32 +203,27 @@ func TestIsDestRelative(t *testing.T) {
53 | },
54 | {
55 | base: "/dir",
56 | - dest: "link",
57 | + dest: "/dir/link",
58 | relative: true,
59 | },
60 | {
61 | base: "/dir",
62 | - dest: "int/file/link",
63 | + dest: "/dir/int/../link",
64 | relative: true,
65 | },
66 | {
67 | - base: "/dir",
68 | - dest: "int/../link",
69 | + base: "dir",
70 | + dest: "dir/link",
71 | relative: true,
72 | },
73 | {
74 | - base: "/dir",
75 | - dest: "/dir/link",
76 | + base: "dir",
77 | + dest: "dir/int/../link",
78 | relative: true,
79 | },
80 | {
81 | - base: "/dir",
82 | - dest: "/dir/int/../link",
83 | - relative: true,
84 | - },
85 | - {
86 | - base: "/dir",
87 | - dest: "/dir/../../link",
88 | + base: "dir",
89 | + dest: "dir/../../link",
90 | relative: false,
91 | },
92 | }
93 | @@ -816,9 +811,10 @@ func TestUntar(t *testing.T) {
94 | }
95 | return expected + suffix
96 | }
97 | - mkBacktickExpectation := func(expected, suffix string) string {
98 | - dir, _ := filepath.Split(filepath.Clean(expected))
99 | - if len(strings.Split(dir, string(os.PathSeparator))) <= 1 {
100 | + mkBacktickExpectation := func(path, expected, suffix string) string {
101 | + linkTarget := filepath.Join(backtick(path), "link-target")
102 | + baseDir := filepath.Join(testdir, dest)
103 | + if !isDestRelative(baseDir, linkJoin(filepath.Join(baseDir, path), linkTarget)) {
104 | return ""
105 | }
106 | return expected + suffix
107 | @@ -836,7 +832,7 @@ func TestUntar(t *testing.T) {
108 | }, file{
109 | path: f.path + "-outerlink",
110 | linkTarget: filepath.Join(backtick(f.path), "link-target"),
111 | - expected: mkBacktickExpectation(f.expected, "-outerlink"),
112 | + expected: mkBacktickExpectation(f.path, f.expected, "-outerlink"),
113 | }, file{
114 | path: f.path + "-outerlink-abs",
115 | linkTarget: filepath.Join(testdir, "link-target"),
116 | @@ -940,7 +936,7 @@ func TestUntar(t *testing.T) {
117 |
118 | // backtick returns a path to one directory up from the target
119 | func backtick(target string) string {
120 | - rel, _ := filepath.Rel(filepath.Dir(target), "../")
121 | + rel := filepath.Join(filepath.Dir(target), "../")
122 | return rel
123 | }
124 |
125 |
126 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
127 | From: Tim Allclair
128 | Date: Fri, 12 Jul 2019 11:53:10 -0700
129 | Subject: [PATCH 2/2] refactors to kubernetes cp command
130 |
131 | ---
132 | pkg/kubectl/cmd/cp.go | 34 +++++------
133 | pkg/kubectl/cmd/cp_test.go | 119 +++++++++++++++++++++----------------
134 | 2 files changed, 84 insertions(+), 69 deletions(-)
135 |
136 | diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go
137 | index 18a5c0176bc..228ce3f7368 100644
138 | --- a/pkg/kubectl/cmd/cp.go
139 | +++ b/pkg/kubectl/cmd/cp.go
140 | @@ -366,9 +366,14 @@ func untarAll(reader io.Reader, destDir, prefix string) error {
141 |
142 | // basic file information
143 | mode := header.FileInfo().Mode()
144 | - destFileName := path.Join(destDir, header.Name[len(prefix):])
145 | - baseName := path.Dir(destFileName)
146 | + destFileName := filepath.Join(destDir, header.Name[len(prefix):])
147 |
148 | + if !isDestRelative(destDir, destFileName) {
149 | + fmt.Fprintf(os.Stderr, "warning: file %q is outside target destination, skipping\n", destFileName)
150 | + continue
151 | + }
152 | +
153 | + baseName := filepath.Dir(destFileName)
154 | if err := os.MkdirAll(baseName, 0755); err != nil {
155 | return err
156 | }
157 | @@ -382,15 +387,14 @@ func untarAll(reader io.Reader, destDir, prefix string) error {
158 | // We need to ensure that the destination file is always within boundries
159 | // of the destination directory. This prevents any kind of path traversal
160 | // from within tar archive.
161 | - dir, file := filepath.Split(destFileName)
162 | - evaledPath, err := filepath.EvalSymlinks(dir)
163 | + evaledPath, err := filepath.EvalSymlinks(baseName)
164 | if err != nil {
165 | return err
166 | }
167 | // For scrutiny we verify both the actual destination as well as we follow
168 | // all the links that might lead outside of the destination directory.
169 | - if !isDestRelative(destDir, destFileName) || !isDestRelative(destDir, filepath.Join(evaledPath, file)) {
170 | - fmt.Fprintf(os.Stderr, "warning: link %q is pointing to %q which is outside target destination, skipping\n", destFileName, header.Linkname)
171 | + if !isDestRelative(destDir, filepath.Join(evaledPath, filepath.Base(destFileName))) {
172 | + fmt.Fprintf(os.Stderr, "warning: file %q is outside target destination, skipping\n", destFileName)
173 | continue
174 | }
175 |
176 | @@ -399,7 +403,11 @@ func untarAll(reader io.Reader, destDir, prefix string) error {
177 | // We need to ensure that the link destination is always within boundries
178 | // of the destination directory. This prevents any kind of path traversal
179 | // from within tar archive.
180 | - if !isDestRelative(destDir, linkJoin(destFileName, linkname)) {
181 | + linkTarget := linkname
182 | + if !filepath.IsAbs(linkname) {
183 | + linkTarget = filepath.Join(evaledPath, linkname)
184 | + }
185 | + if !isDestRelative(destDir, linkTarget) {
186 | fmt.Fprintf(os.Stderr, "warning: link %q is pointing to %q which is outside target destination, skipping\n", destFileName, header.Linkname)
187 | continue
188 | }
189 | @@ -424,20 +432,10 @@ func untarAll(reader io.Reader, destDir, prefix string) error {
190 | return nil
191 | }
192 |
193 | -// linkJoin joins base and link to get the final path to be created.
194 | -// It will consider whether link is an absolute path or not when returning result.
195 | -func linkJoin(base, link string) string {
196 | - if filepath.IsAbs(link) {
197 | - return link
198 | - }
199 | - return filepath.Join(filepath.Dir(base), link)
200 | -}
201 | -
202 | // isDestRelative returns true if dest is pointing outside the base directory,
203 | // false otherwise.
204 | func isDestRelative(base, dest string) bool {
205 | - fullPath := dest
206 | - relative, err := filepath.Rel(base, fullPath)
207 | + relative, err := filepath.Rel(base, dest)
208 | if err != nil {
209 | return false
210 | }
211 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
212 | index 7b58cd92f4b..6795499f9e1 100644
213 | --- a/pkg/kubectl/cmd/cp_test.go
214 | +++ b/pkg/kubectl/cmd/cp_test.go
215 | @@ -30,6 +30,7 @@ import (
216 | "strings"
217 | "testing"
218 |
219 | + "github.com/stretchr/testify/assert"
220 | "github.com/stretchr/testify/require"
221 | "k8s.io/api/core/v1"
222 | "k8s.io/apimachinery/pkg/api/errors"
223 | @@ -769,9 +770,7 @@ func TestUntar(t *testing.T) {
224 | defer os.RemoveAll(testdir)
225 | t.Logf("Test base: %s", testdir)
226 |
227 | - const (
228 | - dest = "base"
229 | - )
230 | + basedir := filepath.Join(testdir, "base")
231 |
232 | type file struct {
233 | path string
234 | @@ -780,26 +779,26 @@ func TestUntar(t *testing.T) {
235 | }
236 | files := []file{{
237 | // Absolute file within dest
238 | - path: filepath.Join(testdir, dest, "abs"),
239 | - expected: filepath.Join(testdir, dest, testdir, dest, "abs"),
240 | + path: filepath.Join(basedir, "abs"),
241 | + expected: filepath.Join(basedir, basedir, "abs"),
242 | }, { // Absolute file outside dest
243 | path: filepath.Join(testdir, "abs-out"),
244 | - expected: filepath.Join(testdir, dest, testdir, "abs-out"),
245 | + expected: filepath.Join(basedir, testdir, "abs-out"),
246 | }, { // Absolute nested file within dest
247 | - path: filepath.Join(testdir, dest, "nested/nest-abs"),
248 | - expected: filepath.Join(testdir, dest, testdir, dest, "nested/nest-abs"),
249 | + path: filepath.Join(basedir, "nested/nest-abs"),
250 | + expected: filepath.Join(basedir, basedir, "nested/nest-abs"),
251 | }, { // Absolute nested file outside dest
252 | - path: filepath.Join(testdir, dest, "nested/../../nest-abs-out"),
253 | - expected: filepath.Join(testdir, dest, testdir, "nest-abs-out"),
254 | + path: filepath.Join(basedir, "nested/../../nest-abs-out"),
255 | + expected: filepath.Join(basedir, testdir, "nest-abs-out"),
256 | }, { // Relative file inside dest
257 | path: "relative",
258 | - expected: filepath.Join(testdir, dest, "relative"),
259 | + expected: filepath.Join(basedir, "relative"),
260 | }, { // Relative file outside dest
261 | path: "../unrelative",
262 | expected: "",
263 | }, { // Nested relative file inside dest
264 | path: "nested/nest-rel",
265 | - expected: filepath.Join(testdir, dest, "nested/nest-rel"),
266 | + expected: filepath.Join(basedir, "nested/nest-rel"),
267 | }, { // Nested relative file outside dest
268 | path: "nested/../../nest-unrelative",
269 | expected: "",
270 | @@ -811,10 +810,11 @@ func TestUntar(t *testing.T) {
271 | }
272 | return expected + suffix
273 | }
274 | - mkBacktickExpectation := func(path, expected, suffix string) string {
275 | - linkTarget := filepath.Join(backtick(path), "link-target")
276 | - baseDir := filepath.Join(testdir, dest)
277 | - if !isDestRelative(baseDir, linkJoin(filepath.Join(baseDir, path), linkTarget)) {
278 | + mkBacklinkExpectation := func(expected, suffix string) string {
279 | + // "resolve" the back link relative to the expectation
280 | + targetDir := filepath.Dir(filepath.Dir(expected))
281 | + // If the "resolved" target is not nested in basedir, it is escaping.
282 | + if !filepath.HasPrefix(targetDir, basedir) {
283 | return ""
284 | }
285 | return expected + suffix
286 | @@ -827,17 +827,27 @@ func TestUntar(t *testing.T) {
287 | expected: mkExpectation(f.expected, "-innerlink"),
288 | }, file{
289 | path: f.path + "-innerlink-abs",
290 | - linkTarget: filepath.Join(testdir, dest, "link-target"),
291 | + linkTarget: filepath.Join(basedir, "link-target"),
292 | expected: mkExpectation(f.expected, "-innerlink-abs"),
293 | }, file{
294 | - path: f.path + "-outerlink",
295 | - linkTarget: filepath.Join(backtick(f.path), "link-target"),
296 | - expected: mkBacktickExpectation(f.path, f.expected, "-outerlink"),
297 | + path: f.path + "-backlink",
298 | + linkTarget: filepath.Join("..", "link-target"),
299 | + expected: mkBacklinkExpectation(f.expected, "-backlink"),
300 | }, file{
301 | path: f.path + "-outerlink-abs",
302 | linkTarget: filepath.Join(testdir, "link-target"),
303 | expected: "",
304 | })
305 | +
306 | + if f.expected != "" {
307 | + // outerlink is the number of backticks to escape to testdir
308 | + outerlink, _ := filepath.Rel(f.expected, testdir)
309 | + links = append(links, file{
310 | + path: f.path + "outerlink",
311 | + linkTarget: filepath.Join(outerlink, "link-target"),
312 | + expected: "",
313 | + })
314 | + }
315 | }
316 | files = append(files, links...)
317 |
318 | @@ -846,11 +856,11 @@ func TestUntar(t *testing.T) {
319 | file{
320 | path: "nested/again/back-link",
321 | linkTarget: "../../nested",
322 | - expected: filepath.Join(testdir, dest, "nested/again/back-link"),
323 | + expected: filepath.Join(basedir, "nested/again/back-link"),
324 | },
325 | file{
326 | path: "nested/again/back-link/../../../back-link-file",
327 | - expected: filepath.Join(testdir, dest, "back-link-file"),
328 | + expected: filepath.Join(basedir, "back-link-file"),
329 | })
330 |
331 | // Test chaining back-tick symlinks.
332 | @@ -858,20 +868,11 @@ func TestUntar(t *testing.T) {
333 | file{
334 | path: "nested/back-link-first",
335 | linkTarget: "../",
336 | - expected: filepath.Join(testdir, dest, "nested/back-link-first"),
337 | + expected: filepath.Join(basedir, "nested/back-link-first"),
338 | },
339 | file{
340 | path: "nested/back-link-first/back-link-second",
341 | linkTarget: "../",
342 | - expected: filepath.Join(testdir, dest, "back-link-second"),
343 | - },
344 | - file{
345 | - // This case is chaining together symlinks that step back, so that
346 | - // if you just look at the target relative to the path it appears
347 | - // inside the destination directory, but if you actually follow each
348 | - // step of the path you end up outside the destination directory.
349 | - path: "nested/back-link-first/back-link-second/back-link-term",
350 | - linkTarget: "",
351 | expected: "",
352 | })
353 |
354 | @@ -934,10 +935,32 @@ func TestUntar(t *testing.T) {
355 | }
356 | }
357 |
358 | -// backtick returns a path to one directory up from the target
359 | -func backtick(target string) string {
360 | - rel := filepath.Join(filepath.Dir(target), "../")
361 | - return rel
362 | +func TestUntar_SingleFile(t *testing.T) {
363 | + testdir, err := ioutil.TempDir("", "test-untar")
364 | + require.NoError(t, err)
365 | + defer os.RemoveAll(testdir)
366 | +
367 | + dest := filepath.Join(testdir, "target")
368 | +
369 | + buf := &bytes.Buffer{}
370 | + tw := tar.NewWriter(buf)
371 | +
372 | + const (
373 | + srcName = "source"
374 | + content = "file contents"
375 | + )
376 | + hdr := &tar.Header{
377 | + Name: srcName,
378 | + Mode: 0666,
379 | + Size: int64(len(content)),
380 | + }
381 | + require.NoError(t, tw.WriteHeader(hdr))
382 | + _, err = tw.Write([]byte(content))
383 | + require.NoError(t, err)
384 | + tw.Close()
385 | +
386 | + require.NoError(t, untarAll(buf, filepath.Join(dest), srcName))
387 | + cmpFileData(t, dest, content)
388 | }
389 |
390 | func createTmpFile(t *testing.T, filepath, data string) {
391 | @@ -955,20 +978,14 @@ func createTmpFile(t *testing.T, filepath, data string) {
392 | }
393 |
394 | func cmpFileData(t *testing.T, filePath, data string) {
395 | - f, err := os.Open(filePath)
396 | - if err != nil {
397 | - t.Fatalf("unexpected error: %v", err)
398 | - }
399 | + actual, err := ioutil.ReadFile(filePath)
400 | + require.NoError(t, err)
401 | + assert.EqualValues(t, data, actual)
402 | +}
403 |
404 | - defer f.Close()
405 | - buff := &bytes.Buffer{}
406 | - if _, err := io.Copy(buff, f); err != nil {
407 | - t.Fatal(err)
408 | - }
409 | - if err := f.Close(); err != nil {
410 | - t.Fatal(err)
411 | - }
412 | - if data != string(buff.Bytes()) {
413 | - t.Fatalf("expected: %s, saw: %s", data, string(buff.Bytes()))
414 | - }
415 | +type testWriter testing.T
416 | +
417 | +func (t *testWriter) Write(p []byte) (n int, err error) {
418 | + t.Logf(string(p))
419 | + return len(p), nil
420 | }
421 |
--------------------------------------------------------------------------------
/patches/CVE-2019-11249.1.12.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: M00nF1sh
3 | Date: Mon, 24 Jun 2019 11:16:00 -0700
4 | Subject: [PATCH 1/2] refactors to kubernetes CP command
5 |
6 | ---
7 | pkg/kubectl/cmd/cp.go | 5 +----
8 | pkg/kubectl/cmd/cp_test.go | 36 ++++++++++++++++--------------------
9 | 2 files changed, 17 insertions(+), 24 deletions(-)
10 |
11 | diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go
12 | index f4c945499e8..b7ac616d050 100644
13 | --- a/pkg/kubectl/cmd/cp.go
14 | +++ b/pkg/kubectl/cmd/cp.go
15 | @@ -488,16 +488,13 @@ func linkJoin(base, link string) string {
16 | if filepath.IsAbs(link) {
17 | return link
18 | }
19 | - return filepath.Join(base, link)
20 | + return filepath.Join(filepath.Dir(base), link)
21 | }
22 |
23 | // isDestRelative returns true if dest is pointing outside the base directory,
24 | // false otherwise.
25 | func isDestRelative(base, dest string) bool {
26 | fullPath := dest
27 | - if !filepath.IsAbs(dest) {
28 | - fullPath = filepath.Join(base, dest)
29 | - }
30 | relative, err := filepath.Rel(base, fullPath)
31 | if err != nil {
32 | return false
33 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
34 | index 0615163bf4a..7a84b2a5f65 100644
35 | --- a/pkg/kubectl/cmd/cp_test.go
36 | +++ b/pkg/kubectl/cmd/cp_test.go
37 | @@ -197,12 +197,12 @@ func TestIsDestRelative(t *testing.T) {
38 | }{
39 | {
40 | base: "/dir",
41 | - dest: "../link",
42 | + dest: "/dir/../link",
43 | relative: false,
44 | },
45 | {
46 | base: "/dir",
47 | - dest: "../../link",
48 | + dest: "/dir/../../link",
49 | relative: false,
50 | },
51 | {
52 | @@ -212,32 +212,27 @@ func TestIsDestRelative(t *testing.T) {
53 | },
54 | {
55 | base: "/dir",
56 | - dest: "link",
57 | + dest: "/dir/link",
58 | relative: true,
59 | },
60 | {
61 | base: "/dir",
62 | - dest: "int/file/link",
63 | + dest: "/dir/int/../link",
64 | relative: true,
65 | },
66 | {
67 | - base: "/dir",
68 | - dest: "int/../link",
69 | + base: "dir",
70 | + dest: "dir/link",
71 | relative: true,
72 | },
73 | {
74 | - base: "/dir",
75 | - dest: "/dir/link",
76 | + base: "dir",
77 | + dest: "dir/int/../link",
78 | relative: true,
79 | },
80 | {
81 | - base: "/dir",
82 | - dest: "/dir/int/../link",
83 | - relative: true,
84 | - },
85 | - {
86 | - base: "/dir",
87 | - dest: "/dir/../../link",
88 | + base: "dir",
89 | + dest: "dir/../../link",
90 | relative: false,
91 | },
92 | }
93 | @@ -751,9 +746,10 @@ func TestUntar(t *testing.T) {
94 | }
95 | return expected + suffix
96 | }
97 | - mkBacktickExpectation := func(expected, suffix string) string {
98 | - dir, _ := filepath.Split(filepath.Clean(expected))
99 | - if len(strings.Split(dir, string(os.PathSeparator))) <= 1 {
100 | + mkBacktickExpectation := func(path, expected, suffix string) string {
101 | + linkTarget := filepath.Join(backtick(path), "link-target")
102 | + baseDir := filepath.Join(testdir, dest)
103 | + if !isDestRelative(baseDir, linkJoin(filepath.Join(baseDir, path), linkTarget)) {
104 | return ""
105 | }
106 | return expected + suffix
107 | @@ -771,7 +767,7 @@ func TestUntar(t *testing.T) {
108 | }, file{
109 | path: f.path + "-outerlink",
110 | linkTarget: filepath.Join(backtick(f.path), "link-target"),
111 | - expected: mkBacktickExpectation(f.expected, "-outerlink"),
112 | + expected: mkBacktickExpectation(f.path, f.expected, "-outerlink"),
113 | }, file{
114 | path: f.path + "-outerlink-abs",
115 | linkTarget: filepath.Join(testdir, "link-target"),
116 | @@ -877,7 +873,7 @@ func TestUntar(t *testing.T) {
117 |
118 | // backtick returns a path to one directory up from the target
119 | func backtick(target string) string {
120 | - rel, _ := filepath.Rel(filepath.Dir(target), "../")
121 | + rel := filepath.Join(filepath.Dir(target), "../")
122 | return rel
123 | }
124 |
125 |
126 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
127 | From: Tim Allclair
128 | Date: Fri, 12 Jul 2019 11:53:10 -0700
129 | Subject: [PATCH 2/2] refactors to kubernetes cp command
130 |
131 | ---
132 | pkg/kubectl/cmd/cp.go | 34 +++++-----
133 | pkg/kubectl/cmd/cp_test.go | 129 ++++++++++++++++++++++---------------
134 | 2 files changed, 92 insertions(+), 71 deletions(-)
135 |
136 | diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go
137 | index b7ac616d050..a32edd7c396 100644
138 | --- a/pkg/kubectl/cmd/cp.go
139 | +++ b/pkg/kubectl/cmd/cp.go
140 | @@ -424,9 +424,14 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
141 |
142 | // basic file information
143 | mode := header.FileInfo().Mode()
144 | - destFileName := path.Join(destDir, header.Name[len(prefix):])
145 | - baseName := path.Dir(destFileName)
146 | + destFileName := filepath.Join(destDir, header.Name[len(prefix):])
147 |
148 | + if !isDestRelative(destDir, destFileName) {
149 | + fmt.Fprintf(o.IOStreams.ErrOut, "warning: file %q is outside target destination, skipping\n", destFileName)
150 | + continue
151 | + }
152 | +
153 | + baseName := filepath.Dir(destFileName)
154 | if err := os.MkdirAll(baseName, 0755); err != nil {
155 | return err
156 | }
157 | @@ -440,15 +445,14 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
158 | // We need to ensure that the destination file is always within boundries
159 | // of the destination directory. This prevents any kind of path traversal
160 | // from within tar archive.
161 | - dir, file := filepath.Split(destFileName)
162 | - evaledPath, err := filepath.EvalSymlinks(dir)
163 | + evaledPath, err := filepath.EvalSymlinks(baseName)
164 | if err != nil {
165 | return err
166 | }
167 | // For scrutiny we verify both the actual destination as well as we follow
168 | // all the links that might lead outside of the destination directory.
169 | - if !isDestRelative(destDir, destFileName) || !isDestRelative(destDir, filepath.Join(evaledPath, file)) {
170 | - fmt.Fprintf(o.IOStreams.ErrOut, "warning: link %q is pointing to %q which is outside target destination, skipping\n", destFileName, header.Linkname)
171 | + if !isDestRelative(destDir, filepath.Join(evaledPath, filepath.Base(destFileName))) {
172 | + fmt.Fprintf(o.IOStreams.ErrOut, "warning: file %q is outside target destination, skipping\n", destFileName)
173 | continue
174 | }
175 |
176 | @@ -457,7 +461,11 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
177 | // We need to ensure that the link destination is always within boundries
178 | // of the destination directory. This prevents any kind of path traversal
179 | // from within tar archive.
180 | - if !isDestRelative(destDir, linkJoin(destFileName, linkname)) {
181 | + linkTarget := linkname
182 | + if !filepath.IsAbs(linkname) {
183 | + linkTarget = filepath.Join(evaledPath, linkname)
184 | + }
185 | + if !isDestRelative(destDir, linkTarget) {
186 | fmt.Fprintf(o.IOStreams.ErrOut, "warning: link %q is pointing to %q which is outside target destination, skipping\n", destFileName, header.Linkname)
187 | continue
188 | }
189 | @@ -482,20 +490,10 @@ func (o *CopyOptions) untarAll(reader io.Reader, destDir, prefix string) error {
190 | return nil
191 | }
192 |
193 | -// linkJoin joins base and link to get the final path to be created.
194 | -// It will consider whether link is an absolute path or not when returning result.
195 | -func linkJoin(base, link string) string {
196 | - if filepath.IsAbs(link) {
197 | - return link
198 | - }
199 | - return filepath.Join(filepath.Dir(base), link)
200 | -}
201 | -
202 | // isDestRelative returns true if dest is pointing outside the base directory,
203 | // false otherwise.
204 | func isDestRelative(base, dest string) bool {
205 | - fullPath := dest
206 | - relative, err := filepath.Rel(base, fullPath)
207 | + relative, err := filepath.Rel(base, dest)
208 | if err != nil {
209 | return false
210 | }
211 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
212 | index 7a84b2a5f65..e426b5cc4e8 100644
213 | --- a/pkg/kubectl/cmd/cp_test.go
214 | +++ b/pkg/kubectl/cmd/cp_test.go
215 | @@ -29,6 +29,7 @@ import (
216 | "strings"
217 | "testing"
218 |
219 | + "github.com/stretchr/testify/assert"
220 | "github.com/stretchr/testify/require"
221 |
222 | "k8s.io/api/core/v1"
223 | @@ -704,9 +705,7 @@ func TestUntar(t *testing.T) {
224 | defer os.RemoveAll(testdir)
225 | t.Logf("Test base: %s", testdir)
226 |
227 | - const (
228 | - dest = "base"
229 | - )
230 | + basedir := filepath.Join(testdir, "base")
231 |
232 | type file struct {
233 | path string
234 | @@ -715,26 +714,26 @@ func TestUntar(t *testing.T) {
235 | }
236 | files := []file{{
237 | // Absolute file within dest
238 | - path: filepath.Join(testdir, dest, "abs"),
239 | - expected: filepath.Join(testdir, dest, testdir, dest, "abs"),
240 | + path: filepath.Join(basedir, "abs"),
241 | + expected: filepath.Join(basedir, basedir, "abs"),
242 | }, { // Absolute file outside dest
243 | path: filepath.Join(testdir, "abs-out"),
244 | - expected: filepath.Join(testdir, dest, testdir, "abs-out"),
245 | + expected: filepath.Join(basedir, testdir, "abs-out"),
246 | }, { // Absolute nested file within dest
247 | - path: filepath.Join(testdir, dest, "nested/nest-abs"),
248 | - expected: filepath.Join(testdir, dest, testdir, dest, "nested/nest-abs"),
249 | + path: filepath.Join(basedir, "nested/nest-abs"),
250 | + expected: filepath.Join(basedir, basedir, "nested/nest-abs"),
251 | }, { // Absolute nested file outside dest
252 | - path: filepath.Join(testdir, dest, "nested/../../nest-abs-out"),
253 | - expected: filepath.Join(testdir, dest, testdir, "nest-abs-out"),
254 | + path: filepath.Join(basedir, "nested/../../nest-abs-out"),
255 | + expected: filepath.Join(basedir, testdir, "nest-abs-out"),
256 | }, { // Relative file inside dest
257 | path: "relative",
258 | - expected: filepath.Join(testdir, dest, "relative"),
259 | + expected: filepath.Join(basedir, "relative"),
260 | }, { // Relative file outside dest
261 | path: "../unrelative",
262 | expected: "",
263 | }, { // Nested relative file inside dest
264 | path: "nested/nest-rel",
265 | - expected: filepath.Join(testdir, dest, "nested/nest-rel"),
266 | + expected: filepath.Join(basedir, "nested/nest-rel"),
267 | }, { // Nested relative file outside dest
268 | path: "nested/../../nest-unrelative",
269 | expected: "",
270 | @@ -746,10 +745,11 @@ func TestUntar(t *testing.T) {
271 | }
272 | return expected + suffix
273 | }
274 | - mkBacktickExpectation := func(path, expected, suffix string) string {
275 | - linkTarget := filepath.Join(backtick(path), "link-target")
276 | - baseDir := filepath.Join(testdir, dest)
277 | - if !isDestRelative(baseDir, linkJoin(filepath.Join(baseDir, path), linkTarget)) {
278 | + mkBacklinkExpectation := func(expected, suffix string) string {
279 | + // "resolve" the back link relative to the expectation
280 | + targetDir := filepath.Dir(filepath.Dir(expected))
281 | + // If the "resolved" target is not nested in basedir, it is escaping.
282 | + if !filepath.HasPrefix(targetDir, basedir) {
283 | return ""
284 | }
285 | return expected + suffix
286 | @@ -762,17 +762,27 @@ func TestUntar(t *testing.T) {
287 | expected: mkExpectation(f.expected, "-innerlink"),
288 | }, file{
289 | path: f.path + "-innerlink-abs",
290 | - linkTarget: filepath.Join(testdir, dest, "link-target"),
291 | + linkTarget: filepath.Join(basedir, "link-target"),
292 | expected: mkExpectation(f.expected, "-innerlink-abs"),
293 | }, file{
294 | - path: f.path + "-outerlink",
295 | - linkTarget: filepath.Join(backtick(f.path), "link-target"),
296 | - expected: mkBacktickExpectation(f.path, f.expected, "-outerlink"),
297 | + path: f.path + "-backlink",
298 | + linkTarget: filepath.Join("..", "link-target"),
299 | + expected: mkBacklinkExpectation(f.expected, "-backlink"),
300 | }, file{
301 | path: f.path + "-outerlink-abs",
302 | linkTarget: filepath.Join(testdir, "link-target"),
303 | expected: "",
304 | })
305 | +
306 | + if f.expected != "" {
307 | + // outerlink is the number of backticks to escape to testdir
308 | + outerlink, _ := filepath.Rel(f.expected, testdir)
309 | + links = append(links, file{
310 | + path: f.path + "outerlink",
311 | + linkTarget: filepath.Join(outerlink, "link-target"),
312 | + expected: "",
313 | + })
314 | + }
315 | }
316 | files = append(files, links...)
317 |
318 | @@ -781,11 +791,11 @@ func TestUntar(t *testing.T) {
319 | file{
320 | path: "nested/again/back-link",
321 | linkTarget: "../../nested",
322 | - expected: filepath.Join(testdir, dest, "nested/again/back-link"),
323 | + expected: filepath.Join(basedir, "nested/again/back-link"),
324 | },
325 | file{
326 | path: "nested/again/back-link/../../../back-link-file",
327 | - expected: filepath.Join(testdir, dest, "back-link-file"),
328 | + expected: filepath.Join(basedir, "back-link-file"),
329 | })
330 |
331 | // Test chaining back-tick symlinks.
332 | @@ -793,20 +803,11 @@ func TestUntar(t *testing.T) {
333 | file{
334 | path: "nested/back-link-first",
335 | linkTarget: "../",
336 | - expected: filepath.Join(testdir, dest, "nested/back-link-first"),
337 | + expected: filepath.Join(basedir, "nested/back-link-first"),
338 | },
339 | file{
340 | path: "nested/back-link-first/back-link-second",
341 | linkTarget: "../",
342 | - expected: filepath.Join(testdir, dest, "back-link-second"),
343 | - },
344 | - file{
345 | - // This case is chaining together symlinks that step back, so that
346 | - // if you just look at the target relative to the path it appears
347 | - // inside the destination directory, but if you actually follow each
348 | - // step of the path you end up outside the destination directory.
349 | - path: "nested/back-link-first/back-link-second/back-link-term",
350 | - linkTarget: "",
351 | expected: "",
352 | })
353 |
354 | @@ -846,9 +847,11 @@ func TestUntar(t *testing.T) {
355 | }
356 | tw.Close()
357 |
358 | - opts := NewCopyOptions(genericclioptions.NewTestIOStreamsDiscard())
359 | + // Capture warnings to stderr for debugging.
360 | + output := (*testWriter)(t)
361 | + opts := NewCopyOptions(genericclioptions.IOStreams{In: &bytes.Buffer{}, Out: output, ErrOut: output})
362 |
363 | - require.NoError(t, opts.untarAll(buf, filepath.Join(testdir, dest), ""))
364 | + require.NoError(t, opts.untarAll(buf, filepath.Join(basedir), ""))
365 |
366 | filepath.Walk(testdir, func(path string, info os.FileInfo, err error) error {
367 | if err != nil {
368 | @@ -871,10 +874,36 @@ func TestUntar(t *testing.T) {
369 | }
370 | }
371 |
372 | -// backtick returns a path to one directory up from the target
373 | -func backtick(target string) string {
374 | - rel := filepath.Join(filepath.Dir(target), "../")
375 | - return rel
376 | +func TestUntar_SingleFile(t *testing.T) {
377 | + testdir, err := ioutil.TempDir("", "test-untar")
378 | + require.NoError(t, err)
379 | + defer os.RemoveAll(testdir)
380 | +
381 | + dest := filepath.Join(testdir, "target")
382 | +
383 | + buf := &bytes.Buffer{}
384 | + tw := tar.NewWriter(buf)
385 | +
386 | + const (
387 | + srcName = "source"
388 | + content = "file contents"
389 | + )
390 | + hdr := &tar.Header{
391 | + Name: srcName,
392 | + Mode: 0666,
393 | + Size: int64(len(content)),
394 | + }
395 | + require.NoError(t, tw.WriteHeader(hdr))
396 | + _, err = tw.Write([]byte(content))
397 | + require.NoError(t, err)
398 | + tw.Close()
399 | +
400 | + // Capture warnings to stderr for debugging.
401 | + output := (*testWriter)(t)
402 | + opts := NewCopyOptions(genericclioptions.IOStreams{In: &bytes.Buffer{}, Out: output, ErrOut: output})
403 | +
404 | + require.NoError(t, opts.untarAll(buf, filepath.Join(dest), srcName))
405 | + cmpFileData(t, dest, content)
406 | }
407 |
408 | func createTmpFile(t *testing.T, filepath, data string) {
409 | @@ -892,20 +921,14 @@ func createTmpFile(t *testing.T, filepath, data string) {
410 | }
411 |
412 | func cmpFileData(t *testing.T, filePath, data string) {
413 | - f, err := os.Open(filePath)
414 | - if err != nil {
415 | - t.Fatalf("unexpected error: %v", err)
416 | - }
417 | + actual, err := ioutil.ReadFile(filePath)
418 | + require.NoError(t, err)
419 | + assert.EqualValues(t, data, actual)
420 | +}
421 |
422 | - defer f.Close()
423 | - buff := &bytes.Buffer{}
424 | - if _, err := io.Copy(buff, f); err != nil {
425 | - t.Fatal(err)
426 | - }
427 | - if err := f.Close(); err != nil {
428 | - t.Fatal(err)
429 | - }
430 | - if data != string(buff.Bytes()) {
431 | - t.Fatalf("expected: %s, saw: %s", data, string(buff.Bytes()))
432 | - }
433 | +type testWriter testing.T
434 | +
435 | +func (t *testWriter) Write(p []byte) (n int, err error) {
436 | + t.Logf(string(p))
437 | + return len(p), nil
438 | }
439 |
--------------------------------------------------------------------------------
/patches/CVE-2019-11251.1.10.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Tim Allclair
3 | Date: Thu, 5 Sep 2019 11:47:43 -0700
4 | Subject: [PATCH] Reorder symlinks to prevent path escapes
5 |
6 | ---
7 | pkg/kubectl/cmd/cp.go | 29 ++++----
8 | pkg/kubectl/cmd/cp_test.go | 148 ++++++++++++++++++++++---------------
9 | 2 files changed, 105 insertions(+), 72 deletions(-)
10 |
11 | diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go
12 | index 228ce3f7368..23e82e2849d 100644
13 | --- a/pkg/kubectl/cmd/cp.go
14 | +++ b/pkg/kubectl/cmd/cp.go
15 | @@ -346,6 +346,7 @@ func clean(fileName string) string {
16 | func untarAll(reader io.Reader, destDir, prefix string) error {
17 | // TODO: use compression here?
18 | tarReader := tar.NewReader(reader)
19 | + symlinks := map[string]string{} // map of link -> destination
20 | for {
21 | header, err := tarReader.Next()
22 | if err != nil {
23 | @@ -399,21 +400,10 @@ func untarAll(reader io.Reader, destDir, prefix string) error {
24 | }
25 |
26 | if mode&os.ModeSymlink != 0 {
27 | - linkname := header.Linkname
28 | - // We need to ensure that the link destination is always within boundries
29 | - // of the destination directory. This prevents any kind of path traversal
30 | - // from within tar archive.
31 | - linkTarget := linkname
32 | - if !filepath.IsAbs(linkname) {
33 | - linkTarget = filepath.Join(evaledPath, linkname)
34 | - }
35 | - if !isDestRelative(destDir, linkTarget) {
36 | - fmt.Fprintf(os.Stderr, "warning: link %q is pointing to %q which is outside target destination, skipping\n", destFileName, header.Linkname)
37 | - continue
38 | - }
39 | - if err := os.Symlink(linkname, destFileName); err != nil {
40 | - return err
41 | + if _, exists := symlinks[destFileName]; exists {
42 | + return fmt.Errorf("duplicate symlink: %q", destFileName)
43 | }
44 | + symlinks[destFileName] = header.Linkname
45 | } else {
46 | outFile, err := os.Create(destFileName)
47 | if err != nil {
48 | @@ -429,6 +419,17 @@ func untarAll(reader io.Reader, destDir, prefix string) error {
49 | }
50 | }
51 |
52 | + // Create symlinks after all regular files have been written.
53 | + // Ordering this way prevents writing data outside the destination directory through path
54 | + // traversals.
55 | + // Symlink chaining is prevented due to the directory tree being established (MkdirAll) before
56 | + // creating any symlinks.
57 | + for newname, oldname := range symlinks {
58 | + if err := os.Symlink(oldname, newname); err != nil {
59 | + return err
60 | + }
61 | + }
62 | +
63 | return nil
64 | }
65 |
66 | diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go
67 | index 6795499f9e1..672c99cf0d6 100644
68 | --- a/pkg/kubectl/cmd/cp_test.go
69 | +++ b/pkg/kubectl/cmd/cp_test.go
70 | @@ -299,13 +299,11 @@ func TestTarUntar(t *testing.T) {
71 | {
72 | name: "tricky_relative",
73 | data: path.Join(dir3, "xyz"),
74 | - omitted: true,
75 | fileType: SymLink,
76 | },
77 | {
78 | name: "absolute_path",
79 | data: "/tmp/gakki",
80 | - omitted: true,
81 | fileType: SymLink,
82 | },
83 | }
84 | @@ -764,6 +762,12 @@ func TestCopyToPod(t *testing.T) {
85 | }
86 | }
87 |
88 | +type testFile struct {
89 | + path string
90 | + linkTarget string // For link types
91 | + expected string // Expect to find the file here (or not, if empty)
92 | +}
93 | +
94 | func TestUntar(t *testing.T) {
95 | testdir, err := ioutil.TempDir("", "test-untar")
96 | require.NoError(t, err)
97 | @@ -772,12 +776,7 @@ func TestUntar(t *testing.T) {
98 |
99 | basedir := filepath.Join(testdir, "base")
100 |
101 | - type file struct {
102 | - path string
103 | - linkTarget string // For link types
104 | - expected string // Expect to find the file here (or not, if empty)
105 | - }
106 | - files := []file{{
107 | + files := []testFile{{
108 | // Absolute file within dest
109 | path: filepath.Join(basedir, "abs"),
110 | expected: filepath.Join(basedir, basedir, "abs"),
111 | @@ -810,42 +809,33 @@ func TestUntar(t *testing.T) {
112 | }
113 | return expected + suffix
114 | }
115 | - mkBacklinkExpectation := func(expected, suffix string) string {
116 | - // "resolve" the back link relative to the expectation
117 | - targetDir := filepath.Dir(filepath.Dir(expected))
118 | - // If the "resolved" target is not nested in basedir, it is escaping.
119 | - if !filepath.HasPrefix(targetDir, basedir) {
120 | - return ""
121 | - }
122 | - return expected + suffix
123 | - }
124 | - links := []file{}
125 | + links := []testFile{}
126 | for _, f := range files {
127 | - links = append(links, file{
128 | + links = append(links, testFile{
129 | path: f.path + "-innerlink",
130 | linkTarget: "link-target",
131 | expected: mkExpectation(f.expected, "-innerlink"),
132 | - }, file{
133 | + }, testFile{
134 | path: f.path + "-innerlink-abs",
135 | linkTarget: filepath.Join(basedir, "link-target"),
136 | expected: mkExpectation(f.expected, "-innerlink-abs"),
137 | - }, file{
138 | + }, testFile{
139 | path: f.path + "-backlink",
140 | linkTarget: filepath.Join("..", "link-target"),
141 | - expected: mkBacklinkExpectation(f.expected, "-backlink"),
142 | - }, file{
143 | + expected: mkExpectation(f.expected, "-backlink"),
144 | + }, testFile{
145 | path: f.path + "-outerlink-abs",
146 | linkTarget: filepath.Join(testdir, "link-target"),
147 | - expected: "",
148 | + expected: mkExpectation(f.expected, "-outerlink-abs"),
149 | })
150 |
151 | if f.expected != "" {
152 | // outerlink is the number of backticks to escape to testdir
153 | outerlink, _ := filepath.Rel(f.expected, testdir)
154 | - links = append(links, file{
155 | - path: f.path + "outerlink",
156 | + links = append(links, testFile{
157 | + path: f.path + "-outerlink",
158 | linkTarget: filepath.Join(outerlink, "link-target"),
159 | - expected: "",
160 | + expected: mkExpectation(f.expected, "-outerlink"),
161 | })
162 | }
163 | }
164 | @@ -853,42 +843,104 @@ func TestUntar(t *testing.T) {
165 |
166 | // Test back-tick escaping through a symlink.
167 | files = append(files,
168 | - file{
169 | + testFile{
170 | path: "nested/again/back-link",
171 | linkTarget: "../../nested",
172 | expected: filepath.Join(basedir, "nested/again/back-link"),
173 | },
174 | - file{
175 | + testFile{
176 | path: "nested/again/back-link/../../../back-link-file",
177 | expected: filepath.Join(basedir, "back-link-file"),
178 | })
179 |
180 | // Test chaining back-tick symlinks.
181 | files = append(files,
182 | - file{
183 | + testFile{
184 | path: "nested/back-link-first",
185 | linkTarget: "../",
186 | expected: filepath.Join(basedir, "nested/back-link-first"),
187 | },
188 | - file{
189 | - path: "nested/back-link-first/back-link-second",
190 | - linkTarget: "../",
191 | - expected: "",
192 | + testFile{
193 | + path: "nested/back-link-second",
194 | + linkTarget: "back-link-first/..",
195 | + expected: filepath.Join(basedir, "nested/back-link-second"),
196 | })
197 |
198 | files = append(files,
199 | - file{ // Relative directory path with terminating /
200 | + testFile{ // Relative directory path with terminating /
201 | path: "direct/dir/",
202 | expected: "",
203 | })
204 |
205 | - buf := &bytes.Buffer{}
206 | - tw := tar.NewWriter(buf)
207 | + buf := makeTestTar(t, files)
208 | +
209 | + require.NoError(t, untarAll(buf, filepath.Join(basedir), ""))
210 | +
211 | expectations := map[string]bool{}
212 | for _, f := range files {
213 | if f.expected != "" {
214 | expectations[f.expected] = false
215 | }
216 | + }
217 | + filepath.Walk(testdir, func(path string, info os.FileInfo, err error) error {
218 | + if err != nil {
219 | + return err
220 | + }
221 | + if info.IsDir() {
222 | + return nil // Ignore directories.
223 | + }
224 | + if _, ok := expectations[path]; !ok {
225 | + t.Errorf("Unexpected file at %s", path)
226 | + } else {
227 | + expectations[path] = true
228 | + }
229 | + return nil
230 | + })
231 | + for path, found := range expectations {
232 | + if !found {
233 | + t.Errorf("Missing expected file %s", path)
234 | + }
235 | + }
236 | +}
237 | +
238 | +func TestUntar_NestedSymlinks(t *testing.T) {
239 | + testdir, err := ioutil.TempDir("", "test-untar-nested")
240 | + require.NoError(t, err)
241 | + defer os.RemoveAll(testdir)
242 | + t.Logf("Test base: %s", testdir)
243 | +
244 | + basedir := filepath.Join(testdir, "base")
245 | +
246 | + // Test chaining back-tick symlinks.
247 | + backLinkFirst := testFile{
248 | + path: "nested/back-link-first",
249 | + linkTarget: "../",
250 | + expected: filepath.Join(basedir, "nested/back-link-first"),
251 | + }
252 | + files := []testFile{backLinkFirst, {
253 | + path: "nested/back-link-first/back-link-second",
254 | + linkTarget: "../",
255 | + expected: "",
256 | + }}
257 | +
258 | + buf := makeTestTar(t, files)
259 | +
260 | + // Expect untarAll to fail. The second link will trigger a directory to be created at
261 | + // "nested/back-link-first", which should trigger a file exists error when the back-link-first
262 | + // symlink is created.
263 | + expectedErr := os.LinkError{
264 | + Op: "symlink",
265 | + Old: backLinkFirst.linkTarget,
266 | + New: backLinkFirst.expected,
267 | + Err: fmt.Errorf("file exists")}
268 | + actualErr := untarAll(buf, filepath.Join(basedir), "")
269 | + assert.EqualError(t, actualErr, expectedErr.Error())
270 | +}
271 | +
272 | +func makeTestTar(t *testing.T, files []testFile) *bytes.Buffer {
273 | + buf := &bytes.Buffer{}
274 | + tw := tar.NewWriter(buf)
275 | + for _, f := range files {
276 | if f.linkTarget == "" {
277 | hdr := &tar.Header{
278 | Name: f.path,
279 | @@ -912,27 +964,7 @@ func TestUntar(t *testing.T) {
280 | }
281 | tw.Close()
282 |
283 | - require.NoError(t, untarAll(buf, filepath.Join(testdir, dest), ""))
284 | -
285 | - filepath.Walk(testdir, func(path string, info os.FileInfo, err error) error {
286 | - if err != nil {
287 | - return err
288 | - }
289 | - if info.IsDir() {
290 | - return nil // Ignore directories.
291 | - }
292 | - if _, ok := expectations[path]; !ok {
293 | - t.Errorf("Unexpected file at %s", path)
294 | - } else {
295 | - expectations[path] = true
296 | - }
297 | - return nil
298 | - })
299 | - for path, found := range expectations {
300 | - if !found {
301 | - t.Errorf("Missing expected file %s", path)
302 | - }
303 | - }
304 | + return buf
305 | }
306 |
307 | func TestUntar_SingleFile(t *testing.T) {
308 |
--------------------------------------------------------------------------------
/patches/CVE-2020-8552.1.11.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Han Kang
3 | Date: Wed, 29 Jan 2020 13:39:59 -0800
4 | Subject: [PATCH] blank out value for unbounded client label
5 |
6 | Change-Id: If179557706cbecab0cf16417c8cf2c5536b02559
7 | ---
8 | staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD | 1 -
9 | staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go | 4 ++--
10 | 2 files changed, 2 insertions(+), 3 deletions(-)
11 |
12 | diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
13 | index 6aef95e2dc8..e2dce55ef17 100644
14 | --- a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
15 | +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
16 | @@ -19,7 +19,6 @@ go_library(
17 | deps = [
18 | "//vendor/github.com/emicklei/go-restful:go_default_library",
19 | "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
20 | - "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
21 | "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
22 | ],
23 | )
24 | diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
25 | index 516452e160b..310d8e1c8a5 100644
26 | --- a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
27 | +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
28 | @@ -26,7 +26,6 @@ import (
29 | "sync"
30 | "time"
31 |
32 | - utilnet "k8s.io/apimachinery/pkg/util/net"
33 | "k8s.io/apiserver/pkg/endpoints/request"
34 |
35 | "github.com/emicklei/go-restful"
36 | @@ -192,7 +191,8 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, fn f
37 | // a request. verb must be uppercase to be backwards compatible with existing monitoring tooling.
38 | func MonitorRequest(req *http.Request, verb, resource, subresource, scope, contentType string, httpCode, respSize int, elapsed time.Duration) {
39 | reportedVerb := cleanVerb(verb, req)
40 | - client := cleanUserAgent(utilnet.GetHTTPClient(req))
41 | + // blank out client string here, in order to avoid cardinality issues
42 | + client := ""
43 | elapsedMicroseconds := float64(elapsed / time.Microsecond)
44 | requestCounter.WithLabelValues(reportedVerb, resource, subresource, scope, client, contentType, codeToString(httpCode)).Inc()
45 | requestLatencies.WithLabelValues(reportedVerb, resource, subresource, scope).Observe(elapsedMicroseconds)
46 |
--------------------------------------------------------------------------------
/patches/CVE-2020-8552.1.13.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Han Kang
3 | Date: Wed, 29 Jan 2020 13:39:59 -0800
4 | Subject: [PATCH] blank out value for unbounded client label
5 |
6 | Change-Id: If179557706cbecab0cf16417c8cf2c5536b02559
7 | ---
8 | staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD | 1 -
9 | staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go | 4 ++--
10 | 2 files changed, 2 insertions(+), 3 deletions(-)
11 |
12 | diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
13 | index ea44cdc05e8..57442696162 100644
14 | --- a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
15 | +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
16 | @@ -18,7 +18,6 @@ go_library(
17 | importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/metrics",
18 | importpath = "k8s.io/apiserver/pkg/endpoints/metrics",
19 | deps = [
20 | - "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
21 | "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
22 | "//vendor/github.com/emicklei/go-restful:go_default_library",
23 | "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
24 | diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
25 | index ae16d43bb1e..affb8f35bb7 100644
26 | --- a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
27 | +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
28 | @@ -26,7 +26,6 @@ import (
29 | "sync"
30 | "time"
31 |
32 | - utilnet "k8s.io/apimachinery/pkg/util/net"
33 | "k8s.io/apiserver/pkg/endpoints/request"
34 |
35 | "github.com/emicklei/go-restful"
36 | @@ -192,7 +191,8 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, fn f
37 | // a request. verb must be uppercase to be backwards compatible with existing monitoring tooling.
38 | func MonitorRequest(req *http.Request, verb, resource, subresource, scope, contentType string, httpCode, respSize int, elapsed time.Duration) {
39 | reportedVerb := cleanVerb(verb, req)
40 | - client := cleanUserAgent(utilnet.GetHTTPClient(req))
41 | + // blank out client string here, in order to avoid cardinality issues
42 | + client := ""
43 | elapsedMicroseconds := float64(elapsed / time.Microsecond)
44 | requestCounter.WithLabelValues(reportedVerb, resource, subresource, scope, client, contentType, codeToString(httpCode)).Inc()
45 | requestLatencies.WithLabelValues(reportedVerb, resource, subresource, scope).Observe(elapsedMicroseconds)
46 |
--------------------------------------------------------------------------------
/patches/CVE-2020-8552.1.14.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Han Kang
3 | Date: Wed, 29 Jan 2020 13:39:59 -0800
4 | Subject: [PATCH] blank out value for unbounded client label
5 |
6 | Change-Id: If179557706cbecab0cf16417c8cf2c5536b02559
7 | ---
8 | staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD | 1 -
9 | staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go | 4 ++--
10 | 2 files changed, 2 insertions(+), 3 deletions(-)
11 |
12 | diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
13 | index 4df68923804..39eb0690ebc 100644
14 | --- a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
15 | +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/BUILD
16 | @@ -20,7 +20,6 @@ go_library(
17 | deps = [
18 | "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
19 | "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
20 | - "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
21 | "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
22 | "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
23 | "//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
24 | diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
25 | index 50058503889..8b51456d503 100644
26 | --- a/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
27 | +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go
28 | @@ -28,7 +28,6 @@ import (
29 |
30 | "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
31 | "k8s.io/apimachinery/pkg/types"
32 | - utilnet "k8s.io/apimachinery/pkg/util/net"
33 | utilsets "k8s.io/apimachinery/pkg/util/sets"
34 | "k8s.io/apiserver/pkg/endpoints/request"
35 | "k8s.io/apiserver/pkg/features"
36 | @@ -247,7 +246,8 @@ func RecordLongRunning(req *http.Request, requestInfo *request.RequestInfo, comp
37 | func MonitorRequest(req *http.Request, verb, group, version, resource, subresource, scope, component, contentType string, httpCode, respSize int, elapsed time.Duration) {
38 | reportedVerb := cleanVerb(verb, req)
39 | dryRun := cleanDryRun(req.URL.Query()["dryRun"])
40 | - client := cleanUserAgent(utilnet.GetHTTPClient(req))
41 | + // blank out client string here, in order to avoid cardinality issues
42 | + client := ""
43 | elapsedMicroseconds := float64(elapsed / time.Microsecond)
44 | elapsedSeconds := elapsed.Seconds()
45 | requestCounter.WithLabelValues(reportedVerb, dryRun, group, version, resource, subresource, scope, component, client, contentType, codeToString(httpCode)).Inc()
46 |
--------------------------------------------------------------------------------
/patches/CVE-2020-8555.1.14.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Michelle Au
3 | Date: Thu, 2 Apr 2020 13:47:56 -0700
4 | Subject: [PATCH] Clean up event messages for errors.
5 |
6 | Change-Id: Ib70b50e676b917c4d976f32ee7a19f8fc63b6bc6
7 | ---
8 | pkg/volume/glusterfs/glusterfs.go | 35 ++++++++-----
9 | pkg/volume/quobyte/quobyte.go | 13 ++++-
10 | pkg/volume/scaleio/sio_client.go | 71 ++++++++++++++++++--------
11 | pkg/volume/storageos/storageos_util.go | 12 +++--
12 | 4 files changed, 92 insertions(+), 39 deletions(-)
13 |
14 | diff --git a/pkg/volume/glusterfs/glusterfs.go b/pkg/volume/glusterfs/glusterfs.go
15 | index d357d0aec92..19a9fecd6e0 100644
16 | --- a/pkg/volume/glusterfs/glusterfs.go
17 | +++ b/pkg/volume/glusterfs/glusterfs.go
18 | @@ -28,7 +28,7 @@ import (
19 |
20 | gcli "github.com/heketi/heketi/client/api/go-client"
21 | gapi "github.com/heketi/heketi/pkg/glusterfs/api"
22 | - "k8s.io/api/core/v1"
23 | + v1 "k8s.io/api/core/v1"
24 | "k8s.io/apimachinery/pkg/api/errors"
25 | "k8s.io/apimachinery/pkg/api/resource"
26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 | @@ -702,8 +702,9 @@ func (d *glusterfsVolumeDeleter) Delete() error {
28 | }
29 | err = cli.VolumeDelete(volumeID)
30 | if err != nil {
31 | - klog.Errorf("failed to delete volume %s: %v", volumeName, err)
32 | - return err
33 | + // don't log error details from client calls in events
34 | + klog.V(4).Infof("failed to delete volume %s: %v", volumeName, err)
35 | + return fmt.Errorf("failed to delete volume: see kube-controller-manager.log for details")
36 | }
37 | klog.V(2).Infof("volume %s deleted successfully", volumeName)
38 |
39 | @@ -848,8 +849,9 @@ func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsPersi
40 | volumeReq := &gapi.VolumeCreateRequest{Size: sz, Name: customVolumeName, Clusters: clusterIDs, Gid: gid64, Durability: p.volumeType, GlusterVolumeOptions: p.volumeOptions, Snapshot: snaps}
41 | volume, err := cli.VolumeCreate(volumeReq)
42 | if err != nil {
43 | - klog.Errorf("failed to create volume: %v", err)
44 | - return nil, 0, "", fmt.Errorf("failed to create volume: %v", err)
45 | + // don't log error details from client calls in events
46 | + klog.V(4).Infof("failed to create volume: %v", err)
47 | + return nil, 0, "", fmt.Errorf("failed to create volume: see kube-controller-manager.log for details")
48 | }
49 | klog.V(1).Infof("volume with size %d and name %s created", volume.Size, volume.Name)
50 | volID = volume.Id
51 | @@ -870,7 +872,8 @@ func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsPersi
52 | klog.Errorf("failed to create endpoint/service %v/%v: %v", epNamespace, epServiceName, err)
53 | deleteErr := cli.VolumeDelete(volume.Id)
54 | if deleteErr != nil {
55 | - klog.Errorf("failed to delete volume: %v, manual deletion of the volume required", deleteErr)
56 | + // don't log error details from client calls in events
57 | + klog.V(4).Infof("failed to delete volume: %v, manual deletion of the volume required", deleteErr)
58 | }
59 | return nil, 0, "", fmt.Errorf("failed to create endpoint/service %v/%v: %v", epNamespace, epServiceName, err)
60 | }
61 | @@ -982,8 +985,9 @@ func parseSecret(namespace, secretName string, kubeClient clientset.Interface) (
62 | func getClusterNodes(cli *gcli.Client, cluster string) (dynamicHostIps []string, err error) {
63 | clusterinfo, err := cli.ClusterInfo(cluster)
64 | if err != nil {
65 | - klog.Errorf("failed to get cluster details: %v", err)
66 | - return nil, fmt.Errorf("failed to get cluster details: %v", err)
67 | + // don't log error details from client calls in events
68 | + klog.V(4).Infof("failed to get cluster details: %v", err)
69 | + return nil, fmt.Errorf("failed to get cluster details: see kube-controller-manager.log for details")
70 | }
71 |
72 | // For the dynamically provisioned volume, we gather the list of node IPs
73 | @@ -992,8 +996,9 @@ func getClusterNodes(cli *gcli.Client, cluster string) (dynamicHostIps []string,
74 | for _, node := range clusterinfo.Nodes {
75 | nodeInfo, err := cli.NodeInfo(string(node))
76 | if err != nil {
77 | - klog.Errorf("failed to get host ipaddress: %v", err)
78 | - return nil, fmt.Errorf("failed to get host ipaddress: %v", err)
79 | + // don't log error details from client calls in events
80 | + klog.V(4).Infof("failed to get host ipaddress: %v", err)
81 | + return nil, fmt.Errorf("failed to get host ipaddress: see kube-controller-manager.log for details")
82 | }
83 | ipaddr := dstrings.Join(nodeInfo.NodeAddRequest.Hostnames.Storage, "")
84 | dynamicHostIps = append(dynamicHostIps, ipaddr)
85 | @@ -1250,8 +1255,9 @@ func (plugin *glusterfsPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize res
86 | //Check the existing volume size
87 | currentVolumeInfo, err := cli.VolumeInfo(volumeID)
88 | if err != nil {
89 | - klog.Errorf("error when fetching details of volume %s: %v", volumeName, err)
90 | - return oldSize, err
91 | + // don't log error details from client calls in events
92 | + klog.V(4).Infof("error when fetching details of volume %s: %v", volumeName, err)
93 | + return oldSize, fmt.Errorf("failed to get volume info %s: see kube-controller-manager.log for details", volumeName)
94 | }
95 |
96 | if int64(currentVolumeInfo.Size) >= requestGiB {
97 | @@ -1264,8 +1270,9 @@ func (plugin *glusterfsPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize res
98 | // Expand the volume
99 | volumeInfoRes, err := cli.VolumeExpand(volumeID, volumeExpandReq)
100 | if err != nil {
101 | - klog.Errorf("failed to expand volume %s: %v", volumeName, err)
102 | - return oldSize, err
103 | + // don't log error details from client calls in events
104 | + klog.V(4).Infof("failed to expand volume %s: %v", volumeName, err)
105 | + return oldSize, fmt.Errorf("failed to expand volume: see kube-controller-manager.log for details")
106 | }
107 |
108 | klog.V(2).Infof("volume %s expanded to new size %d successfully", volumeName, volumeInfoRes.Size)
109 | diff --git a/pkg/volume/quobyte/quobyte.go b/pkg/volume/quobyte/quobyte.go
110 | index 087bdaecbf0..7aa277a1562 100644
111 | --- a/pkg/volume/quobyte/quobyte.go
112 | +++ b/pkg/volume/quobyte/quobyte.go
113 | @@ -17,6 +17,7 @@ limitations under the License.
114 | package quobyte
115 |
116 | import (
117 | + "errors"
118 | "fmt"
119 | "os"
120 | "path"
121 | @@ -416,7 +417,9 @@ func (provisioner *quobyteVolumeProvisioner) Provision(selectedNode *v1.Node, al
122 |
123 | vol, sizeGB, err := manager.createVolume(provisioner, createQuota)
124 | if err != nil {
125 | - return nil, err
126 | + // don't log error details from client calls in events
127 | + klog.V(4).Infof("CreateVolume failed: %v", err)
128 | + return nil, errors.New("CreateVolume failed: see kube-controller-manager.log for details")
129 | }
130 | pv := new(v1.PersistentVolume)
131 | metav1.SetMetaDataAnnotation(&pv.ObjectMeta, util.VolumeDynamicallyCreatedByKey, "quobyte-dynamic-provisioner")
132 | @@ -451,7 +454,13 @@ func (deleter *quobyteVolumeDeleter) Delete() error {
133 | manager := &quobyteVolumeManager{
134 | config: cfg,
135 | }
136 | - return manager.deleteVolume(deleter)
137 | + err = manager.deleteVolume(deleter)
138 | + if err != nil {
139 | + // don't log error details from client calls in events
140 | + klog.V(4).Infof("DeleteVolume failed: %v", err)
141 | + return errors.New("DeleteVolume failed: see kube-controller-manager.log for details")
142 | + }
143 | + return nil
144 | }
145 |
146 | // Parse API configuration (url, username and password) out of class.Parameters.
147 | diff --git a/pkg/volume/scaleio/sio_client.go b/pkg/volume/scaleio/sio_client.go
148 | index 2c7041f478e..bfba897cde9 100644
149 | --- a/pkg/volume/scaleio/sio_client.go
150 | +++ b/pkg/volume/scaleio/sio_client.go
151 | @@ -127,8 +127,9 @@ func (c *sioClient) init() error {
152 | Username: c.username,
153 | Password: c.password},
154 | ); err != nil {
155 | - klog.Error(log("client authentication failed: %v", err))
156 | - return err
157 | + // don't log error details from client calls in events
158 | + klog.V(4).Infof(log("client authentication failed: %v", err))
159 | + return errors.New("client authentication failed")
160 | }
161 |
162 | // retrieve system
163 | @@ -215,8 +216,9 @@ func (c *sioClient) CreateVolume(name string, sizeGB int64) (*siotypes.Volume, e
164 | }
165 | createResponse, err := c.client.CreateVolume(params, c.storagePool.Name)
166 | if err != nil {
167 | - klog.Error(log("failed to create volume %s: %v", name, err))
168 | - return nil, err
169 | + // don't log error details from client calls in events
170 | + klog.V(4).Infof(log("failed to create volume %s: %v", name, err))
171 | + return nil, errors.New("failed to create volume: see kubernetes logs for details")
172 | }
173 | return c.Volume(sioVolumeID(createResponse.ID))
174 | }
175 | @@ -244,8 +246,9 @@ func (c *sioClient) AttachVolume(id sioVolumeID, multipleMappings bool) error {
176 | volClient.Volume = &siotypes.Volume{ID: string(id)}
177 |
178 | if err := volClient.MapVolumeSdc(params); err != nil {
179 | - klog.Error(log("failed to attach volume id %s: %v", id, err))
180 | - return err
181 | + // don't log error details from client calls in events
182 | + klog.V(4).Infof(log("failed to attach volume id %s: %v", id, err))
183 | + return errors.New("failed to attach volume: see kubernetes logs for details")
184 | }
185 |
186 | klog.V(4).Info(log("volume %s attached successfully", id))
187 | @@ -270,7 +273,9 @@ func (c *sioClient) DetachVolume(id sioVolumeID) error {
188 | volClient := sio.NewVolume(c.client)
189 | volClient.Volume = &siotypes.Volume{ID: string(id)}
190 | if err := volClient.UnmapVolumeSdc(params); err != nil {
191 | - return err
192 | + // don't log error details from client calls in events
193 | + klog.V(4).Infof(log("failed to detach volume id %s: %v", id, err))
194 | + return errors.New("failed to detach volume: see kubernetes logs for details")
195 | }
196 | return nil
197 | }
198 | @@ -288,7 +293,9 @@ func (c *sioClient) DeleteVolume(id sioVolumeID) error {
199 | volClient := sio.NewVolume(c.client)
200 | volClient.Volume = vol
201 | if err := volClient.RemoveVolume("ONLY_ME"); err != nil {
202 | - return err
203 | + // don't log error details from client calls in events
204 | + klog.V(4).Infof(log("failed to remove volume id %s: %v", id, err))
205 | + return errors.New("failed to remove volume: see kubernetes logs for details")
206 | }
207 | return nil
208 | }
209 | @@ -307,8 +314,9 @@ func (c *sioClient) IID() (string, error) {
210 | }
211 | sdc, err := c.sysClient.FindSdc("SdcGUID", guid)
212 | if err != nil {
213 | - klog.Error(log("failed to retrieve sdc info %s", err))
214 | - return "", err
215 | + // don't log error details from client calls in events
216 | + klog.V(4).Infof(log("failed to retrieve sdc info %s", err))
217 | + return "", errors.New("failed to retrieve sdc info: see kubernetes logs for details")
218 | }
219 | c.instanceID = sdc.Sdc.ID
220 | klog.V(4).Info(log("retrieved instanceID %s", c.instanceID))
221 | @@ -473,12 +481,15 @@ func (c *sioClient) WaitForDetachedDevice(token string) error {
222 | // ***********************************************************************
223 | func (c *sioClient) findSystem(sysname string) (sys *siotypes.System, err error) {
224 | if c.sysClient, err = c.client.FindSystem("", sysname, ""); err != nil {
225 | - return nil, err
226 | + // don't log error details from clients in events
227 | + klog.V(4).Infof(log("failed to find system %q: %v", sysname, err))
228 | + return nil, errors.New("failed to find system: see kubernetes logs for details")
229 | }
230 | systems, err := c.client.GetInstance("")
231 | if err != nil {
232 | - klog.Error(log("failed to retrieve instances: %v", err))
233 | - return nil, err
234 | + // don't log error details from clients in events
235 | + klog.V(4).Infof(log("failed to retrieve instances: %v", err))
236 | + return nil, errors.New("failed to retrieve instances: see kubernetes logs for details")
237 | }
238 | for _, sys = range systems {
239 | if sys.Name == sysname {
240 | @@ -494,8 +505,9 @@ func (c *sioClient) findProtectionDomain(pdname string) (*siotypes.ProtectionDom
241 | if c.sysClient != nil {
242 | protectionDomain, err := c.sysClient.FindProtectionDomain("", pdname, "")
243 | if err != nil {
244 | - klog.Error(log("failed to retrieve protection domains: %v", err))
245 | - return nil, err
246 | + // don't log error details from clients in events
247 | + klog.V(4).Infof(log("failed to retrieve protection domains: %v", err))
248 | + return nil, errors.New("failed to retrieve protection domains: see kubernetes logs for details")
249 | }
250 | c.pdClient.ProtectionDomain = protectionDomain
251 | return protectionDomain, nil
252 | @@ -509,8 +521,9 @@ func (c *sioClient) findStoragePool(spname string) (*siotypes.StoragePool, error
253 | if c.pdClient != nil {
254 | sp, err := c.pdClient.FindStoragePool("", spname, "")
255 | if err != nil {
256 | - klog.Error(log("failed to retrieve storage pool: %v", err))
257 | - return nil, err
258 | + // don't log error details from clients in events
259 | + klog.V(4).Infof(log("failed to retrieve storage pool: %v", err))
260 | + return nil, errors.New("failed to retrieve storage pool: see kubernetes logs for details")
261 | }
262 | c.spClient.StoragePool = sp
263 | return sp, nil
264 | @@ -520,14 +533,32 @@ func (c *sioClient) findStoragePool(spname string) (*siotypes.StoragePool, error
265 | }
266 |
267 | func (c *sioClient) getVolumes() ([]*siotypes.Volume, error) {
268 | - return c.client.GetVolume("", "", "", "", true)
269 | + volumes, err := c.client.GetVolume("", "", "", "", true)
270 | + if err != nil {
271 | + // don't log error details from clients in events
272 | + klog.V(4).Infof(log("failed to get volumes: %v", err))
273 | + return nil, errors.New("failed to get volumes: see kubernetes logs for details")
274 | + }
275 | + return volumes, nil
276 | }
277 | func (c *sioClient) getVolumesByID(id sioVolumeID) ([]*siotypes.Volume, error) {
278 | - return c.client.GetVolume("", string(id), "", "", true)
279 | + volumes, err := c.client.GetVolume("", string(id), "", "", true)
280 | + if err != nil {
281 | + // don't log error details from clients in events
282 | + klog.V(4).Infof(log("failed to get volumes by id: %v", err))
283 | + return nil, errors.New("failed to get volumes by id: see kubernetes logs for details")
284 | + }
285 | + return volumes, nil
286 | }
287 |
288 | func (c *sioClient) getVolumesByName(name string) ([]*siotypes.Volume, error) {
289 | - return c.client.GetVolume("", "", "", name, true)
290 | + volumes, err := c.client.GetVolume("", "", "", name, true)
291 | + if err != nil {
292 | + // don't log error details from clients in events
293 | + klog.V(4).Infof(log("failed to get volumes by name: %v", err))
294 | + return nil, errors.New("failed to get volumes by name: see kubernetes logs for details")
295 | + }
296 | + return volumes, nil
297 | }
298 |
299 | func (c *sioClient) getSdcPath() string {
300 | diff --git a/pkg/volume/storageos/storageos_util.go b/pkg/volume/storageos/storageos_util.go
301 | index eb669186f61..ae06b1ebcc1 100644
302 | --- a/pkg/volume/storageos/storageos_util.go
303 | +++ b/pkg/volume/storageos/storageos_util.go
304 | @@ -122,8 +122,9 @@ func (u *storageosUtil) CreateVolume(p *storageosProvisioner) (*storageosVolume,
305 |
306 | vol, err := u.api.VolumeCreate(opts)
307 | if err != nil {
308 | - klog.Errorf("volume create failed for volume %q (%v)", opts.Name, err)
309 | - return nil, err
310 | + // don't log error details from client calls in events
311 | + klog.V(4).Infof("volume create failed for volume %q (%v)", opts.Name, err)
312 | + return nil, errors.New("volume create failed: see kube-controller-manager.log for details")
313 | }
314 | return &storageosVolume{
315 | ID: vol.ID,
316 | @@ -286,7 +287,12 @@ func (u *storageosUtil) DeleteVolume(d *storageosDeleter) error {
317 | Namespace: d.volNamespace,
318 | Force: true,
319 | }
320 | - return u.api.VolumeDelete(opts)
321 | + if err := u.api.VolumeDelete(opts); err != nil {
322 | + // don't log error details from client calls in events
323 | + klog.V(4).Infof("volume deleted failed for volume %q in namespace %q: %v", d.volName, d.volNamespace, err)
324 | + return errors.New("volume delete failed: see kube-controller-manager.log for details")
325 | + }
326 | + return nil
327 | }
328 |
329 | // Get the node's device path from the API, falling back to the default if not
330 |
--------------------------------------------------------------------------------
/patches/CVE-2020-8558.1.12.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Casey Callendrello
3 | Date: Fri, 29 May 2020 13:03:37 +0200
4 | Subject: [PATCH] kubelet: block non-forwarded packets from crossing the
5 | localhost boundary
6 |
7 | We set route_localnet so that host-network processes can connect to
8 | <127.0.0.1:NodePort> and it still works. This, however, is too
9 | permissive.
10 |
11 | So, block martians that are not already in conntrack.
12 |
13 | See: #90259
14 | Signed-off-by: Casey Callendrello
15 | ---
16 | pkg/kubelet/kubelet_network_linux.go | 16 ++++++++++++++++
17 | 1 file changed, 16 insertions(+)
18 |
19 | diff --git a/pkg/kubelet/kubelet_network_linux.go b/pkg/kubelet/kubelet_network_linux.go
20 | index 002b226b190..f1330b875ca 100644
21 | --- a/pkg/kubelet/kubelet_network_linux.go
22 | +++ b/pkg/kubelet/kubelet_network_linux.go
23 | @@ -68,6 +68,22 @@ func (kl *Kubelet) syncNetworkUtil() {
24 | glog.Errorf("Failed to ensure rule to drop packet marked by %v in %v chain %v: %v", KubeMarkDropChain, utiliptables.TableFilter, KubeFirewallChain, err)
25 | return
26 | }
27 | +
28 | + // drop all non-local packets to localhost if they're not part of an existing
29 | + // forwarded connection. See #90259
30 | + if !kl.iptClient.IsIpv6() { // ipv6 doesn't have this issue
31 | + if _, err := kl.iptClient.EnsureRule(utiliptables.Append, utiliptables.TableFilter, KubeFirewallChain,
32 | + "-m", "comment", "--comment", "block incoming localnet connections",
33 | + "--dst", "127.0.0.0/8",
34 | + "!", "--src", "127.0.0.0/8",
35 | + "-m", "conntrack",
36 | + "!", "--ctstate", "RELATED,ESTABLISHED,DNAT",
37 | + "-j", "DROP"); err != nil {
38 | + glog.Errorf("Failed to ensure rule to drop invalid localhost packets in %v chain %v: %v", utiliptables.TableFilter, KubeFirewallChain, err)
39 | + return
40 | + }
41 | + }
42 | +
43 | if _, err := kl.iptClient.EnsureRule(utiliptables.Prepend, utiliptables.TableFilter, utiliptables.ChainOutput, "-j", string(KubeFirewallChain)); err != nil {
44 | glog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", utiliptables.TableFilter, utiliptables.ChainOutput, KubeFirewallChain, err)
45 | return
46 |
--------------------------------------------------------------------------------
/patches/CVE-2020-8559.1.12.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Tim Allclair
3 | Date: Wed, 17 Jun 2020 11:09:02 -0700
4 | Subject: [PATCH] Don't return proxied redirects to the client
5 |
6 | ---
7 | staging/src/k8s.io/apimachinery/pkg/util/net/http.go | 2 +-
8 | .../k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go | 10 ++++++++++
9 | 2 files changed, 11 insertions(+), 1 deletion(-)
10 |
11 | diff --git a/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
12 | index 7c2a5e6286d..75750aaacc2 100644
13 | --- a/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
14 | +++ b/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
15 | @@ -404,7 +404,7 @@ redirectLoop:
16 |
17 | // Only follow redirects to the same host. Otherwise, propagate the redirect response back.
18 | if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
19 | - break redirectLoop
20 | + return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname())
21 | }
22 |
23 | // Reset the connection.
24 | diff --git a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
25 | index 4c6c5751680..402bef86f3c 100644
26 | --- a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
27 | +++ b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
28 | @@ -284,6 +284,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
29 | rawResponse = headerBytes
30 | }
31 |
32 | + // If the backend did not upgrade the request, return an error to the client. If the response was
33 | + // an error, the error is forwarded directly after the connection is hijacked. Otherwise, just
34 | + // return a generic error here.
35 | + if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 {
36 | + err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode)
37 | + glog.Errorf("Proxy upgrade error: %v", err)
38 | + h.Responder.Error(w, req, err)
39 | + return true
40 | + }
41 | +
42 | // Once the connection is hijacked, the ErrorResponder will no longer work, so
43 | // hijacking should be the last step in the upgrade.
44 | requestHijacker, ok := w.(http.Hijacker)
45 |
--------------------------------------------------------------------------------
/patches/CVE-2020-8559.1.13.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Tim Allclair
3 | Date: Wed, 17 Jun 2020 11:09:02 -0700
4 | Subject: [PATCH] Don't return proxied redirects to the client
5 |
6 | ---
7 | staging/src/k8s.io/apimachinery/pkg/util/net/http.go | 2 +-
8 | .../k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go | 10 ++++++++++
9 | 2 files changed, 11 insertions(+), 1 deletion(-)
10 |
11 | diff --git a/staging/src/k8s.io/apimachinery/pkg/util/net/http.go b/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
12 | index 155667cdfc7..adab4bc0213 100644
13 | --- a/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
14 | +++ b/staging/src/k8s.io/apimachinery/pkg/util/net/http.go
15 | @@ -404,7 +404,7 @@ redirectLoop:
16 |
17 | // Only follow redirects to the same host. Otherwise, propagate the redirect response back.
18 | if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
19 | - break redirectLoop
20 | + return nil, nil, fmt.Errorf("hostname mismatch: expected %s, found %s", originalLocation.Hostname(), location.Hostname())
21 | }
22 |
23 | // Reset the connection.
24 | diff --git a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
25 | index 3c8e09399f5..501deb9c00e 100644
26 | --- a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
27 | +++ b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go
28 | @@ -284,6 +284,16 @@ func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Reques
29 | rawResponse = headerBytes
30 | }
31 |
32 | + // If the backend did not upgrade the request, return an error to the client. If the response was
33 | + // an error, the error is forwarded directly after the connection is hijacked. Otherwise, just
34 | + // return a generic error here.
35 | + if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 {
36 | + err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode)
37 | + klog.Errorf("Proxy upgrade error: %v", err)
38 | + h.Responder.Error(w, req, err)
39 | + return true
40 | + }
41 | +
42 | // Once the connection is hijacked, the ErrorResponder will no longer work, so
43 | // hijacking should be the last step in the upgrade.
44 | requestHijacker, ok := w.(http.Hijacker)
45 |
--------------------------------------------------------------------------------
/patches/fix-etcd-health.1.11.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Jingyi Hu
3 | Date: Tue, 29 Oct 2019 13:10:29 -0700
4 | Subject: [PATCH] Update etcd.sh to use v3 endpoint
5 |
6 | ---
7 | hack/lib/etcd.sh | 4 ++--
8 | 1 file changed, 2 insertions(+), 2 deletions(-)
9 |
10 | diff --git a/hack/lib/etcd.sh b/hack/lib/etcd.sh
11 | index cbe1083daaa..ac098a279a2 100755
12 | --- a/hack/lib/etcd.sh
13 | +++ b/hack/lib/etcd.sh
14 | @@ -78,8 +78,8 @@ kube::etcd::start() {
15 | ETCD_PID=$!
16 |
17 | echo "Waiting for etcd to come up."
18 | - kube::util::wait_for_url "http://${ETCD_HOST}:${ETCD_PORT}/v2/machines" "etcd: " 0.25 80
19 | - curl -fs -X PUT "http://${ETCD_HOST}:${ETCD_PORT}/v2/keys/_test"
20 | + kube::util::wait_for_url "http://${ETCD_HOST}:${ETCD_PORT}/health" "etcd: " 0.25 80
21 | + curl -fs -X POST "http://${ETCD_HOST}:${ETCD_PORT}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}'
22 | }
23 |
24 | kube::etcd::stop() {
25 |
--------------------------------------------------------------------------------
/patches/fix-etcd-health.1.16.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Jingyi Hu
3 | Date: Tue, 29 Oct 2019 13:10:29 -0700
4 | Subject: [PATCH] Update etcd.sh to use v3 endpoint
5 |
6 | ---
7 | hack/lib/etcd.sh | 4 ++--
8 | 1 file changed, 2 insertions(+), 2 deletions(-)
9 |
10 | diff --git a/hack/lib/etcd.sh b/hack/lib/etcd.sh
11 | index fe71c888775..6f7e4c5e18a 100755
12 | --- a/hack/lib/etcd.sh
13 | +++ b/hack/lib/etcd.sh
14 | @@ -80,8 +80,8 @@ kube::etcd::start() {
15 | ETCD_PID=$!
16 |
17 | echo "Waiting for etcd to come up."
18 | - kube::util::wait_for_url "${KUBE_INTEGRATION_ETCD_URL}/v2/machines" "etcd: " 0.25 80
19 | - curl -fs -X PUT "${KUBE_INTEGRATION_ETCD_URL}/v2/keys/_test"
20 | + kube::util::wait_for_url "${KUBE_INTEGRATION_ETCD_URL}/health" "etcd: " 0.25 80
21 | + curl -fs -X POST "${KUBE_INTEGRATION_ETCD_URL}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}'
22 | }
23 |
24 | kube::etcd::stop() {
25 |
--------------------------------------------------------------------------------
/patches/fix-etcd-put-key.1.11.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Wed, 28 Jul 2021 10:32:45 +0800
4 | Subject: [PATCH] Remove writable verification in etcd startup
5 |
6 | ---
7 | hack/lib/etcd.sh | 1 -
8 | 1 file changed, 1 deletion(-)
9 |
10 | diff --git a/hack/lib/etcd.sh b/hack/lib/etcd.sh
11 | index ac098a279a2..036d63ae374 100755
12 | --- a/hack/lib/etcd.sh
13 | +++ b/hack/lib/etcd.sh
14 | @@ -79,7 +79,6 @@ kube::etcd::start() {
15 |
16 | echo "Waiting for etcd to come up."
17 | kube::util::wait_for_url "http://${ETCD_HOST}:${ETCD_PORT}/health" "etcd: " 0.25 80
18 | - curl -fs -X POST "http://${ETCD_HOST}:${ETCD_PORT}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}'
19 | }
20 |
21 | kube::etcd::stop() {
22 |
--------------------------------------------------------------------------------
/patches/fix-etcd-put-key.1.23.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Wed, 28 Jul 2021 10:32:45 +0800
4 | Subject: [PATCH] Remove writable verification in etcd startup
5 |
6 | ---
7 | hack/lib/etcd.sh | 1 -
8 | 1 file changed, 1 deletion(-)
9 |
10 | diff --git a/hack/lib/etcd.sh b/hack/lib/etcd.sh
11 | index a548dc59c45..515187c2adc 100755
12 | --- a/hack/lib/etcd.sh
13 | +++ b/hack/lib/etcd.sh
14 | @@ -88,7 +88,6 @@ kube::etcd::start() {
15 |
16 | echo "Waiting for etcd to come up."
17 | kube::util::wait_for_url "${KUBE_INTEGRATION_ETCD_URL}/health" "etcd: " 0.25 80
18 | - curl -fs -X POST "${KUBE_INTEGRATION_ETCD_URL}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}'
19 | }
20 |
21 | kube::etcd::start_scraping() {
22 |
--------------------------------------------------------------------------------
/patches/fix-etcd-put-key.1.24.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Wed, 28 Jul 2021 10:32:45 +0800
4 | Subject: [PATCH] Remove writable verification in etcd startup
5 |
6 | ---
7 | hack/lib/etcd.sh | 1 -
8 | 1 file changed, 1 deletion(-)
9 |
10 | diff --git a/hack/lib/etcd.sh b/hack/lib/etcd.sh
11 | index 307d241d294..b01dd760bcc 100755
12 | --- a/hack/lib/etcd.sh
13 | +++ b/hack/lib/etcd.sh
14 | @@ -92,7 +92,6 @@ kube::etcd::start() {
15 |
16 | echo "Waiting for etcd to come up."
17 | kube::util::wait_for_url "${KUBE_INTEGRATION_ETCD_URL}/health" "etcd: " 0.25 80
18 | - curl -fs -X POST "${KUBE_INTEGRATION_ETCD_URL}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}'
19 | }
20 |
21 | kube::etcd::start_scraping() {
22 |
--------------------------------------------------------------------------------
/patches/fix-image-name.1.12.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: =?UTF-8?q?Javier=20P=C3=A9rez=20Hern=C3=A1ndez?=
3 | Date: Thu, 11 Jul 2019 10:58:32 -0700
4 | Subject: [PATCH] release lib: docker save remove special name for amd64
5 |
6 | ---
7 | build/lib/release.sh | 16 ++--------------
8 | 1 file changed, 2 insertions(+), 14 deletions(-)
9 |
10 | diff --git a/build/lib/release.sh b/build/lib/release.sh
11 | index ef7a5838e73..5f1ea62fd94 100644
12 | --- a/build/lib/release.sh
13 | +++ b/build/lib/release.sh
14 | @@ -335,20 +335,8 @@ function kube::release::create_docker_images_for_server() {
15 | local docker_build_path="${binary_dir}/${binary_name}.dockerbuild"
16 | local docker_file_path="${docker_build_path}/Dockerfile"
17 | local binary_file_path="${binary_dir}/${binary_name}"
18 | - local docker_image_tag="${docker_registry}"
19 | - local deprecated_image_tag="${deprecated_registry}"
20 | - if [[ ${arch} == "amd64" ]]; then
21 | - # If we are building a amd64 docker image, preserve the original
22 | - # image name
23 | - docker_image_tag+="/${binary_name}:${docker_tag}"
24 | - deprecated_image_tag+="/${binary_name}:${docker_tag}"
25 | - else
26 | - # If we are building a docker image for another architecture,
27 | - # append the arch in the image tag
28 | - docker_image_tag+="/${binary_name}-${arch}:${docker_tag}"
29 | - deprecated_image_tag+="/${binary_name}-${arch}:${docker_tag}"
30 | - fi
31 | -
32 | + local docker_image_tag="${docker_registry}/${binary_name}-${arch}:${docker_tag}"
33 | + local deprecated_image_tag="${deprecated_registry}/${binary_name}-${arch}:${docker_tag}"
34 |
35 | kube::log::status "Starting docker build for image: ${binary_name}-${arch}"
36 | (
37 |
--------------------------------------------------------------------------------
/patches/fix-kubectl-convert-97644.1.20.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Masashi Honma
3 | Date: Thu, 18 Feb 2021 08:24:07 +0900
4 | Subject: [PATCH] Fix tests using kubectl convert
5 |
6 | hack/make-rules/test-cmd.sh script fails with tariling errors.
7 |
8 | Error: unknown command "convert" for "kubectl"
9 |
10 | 1. This PR fixes the errors by replacing or removing the use of
11 | "kubectl convert" option because it was already removed.
12 |
13 | 2. Fix trailing shell check failure as well.
14 | In ./test/cmd/generic-resources.sh line 366:
15 | kube::test::get_object_assert deployment "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_NGINX}:${IMAGE_NGINX}:"
16 | ---
17 | test/cmd/create.sh | 2 +-
18 | test/cmd/generic-resources.sh | 30 ++----------------------------
19 | test/cmd/template-output.sh | 4 ----
20 | 3 files changed, 3 insertions(+), 33 deletions(-)
21 |
22 | diff --git a/test/cmd/create.sh b/test/cmd/create.sh
23 | index 20f0e8add96..67bcf8ff59d 100755
24 | --- a/test/cmd/create.sh
25 | +++ b/test/cmd/create.sh
26 | @@ -85,7 +85,7 @@ run_kubectl_create_error_tests() {
27 | rm "${ERROR_FILE}"
28 |
29 | # Posting a pod to namespaces should fail. Also tests --raw forcing the post location
30 | - grep -q "cannot be handled as a Namespace: converting (v1.Pod)" <<< "$( kubectl convert -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o json | kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f - --v=8 2>&1 )"
31 | + grep -q 'the object provided is unrecognized (must be of type Namespace)' <<< "$( kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml --v=8 2>&1 )"
32 |
33 | grep -q "raw and --edit are mutually exclusive" <<< "$( kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml --edit 2>&1 )"
34 |
35 | diff --git a/test/cmd/generic-resources.sh b/test/cmd/generic-resources.sh
36 | index 17f111580b2..b983118d463 100755
37 | --- a/test/cmd/generic-resources.sh
38 | +++ b/test/cmd/generic-resources.sh
39 | @@ -259,32 +259,6 @@ run_recursive_resources_tests() {
40 | kube::test::get_object_assert pods "{{range.items}}{{${labels_field}.status}}:{{end}}" 'replaced:replaced:'
41 | kube::test::if_has_string "${output_message}" 'error validating data: kind not set'
42 |
43 | -
44 | - ### Convert deployment YAML file locally without affecting the live deployment.
45 | - # Pre-condition: no deployments exist
46 | - kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
47 | - # Command
48 | - # Create a deployment (revision 1)
49 | - kubectl create -f hack/testdata/deployment-revision1.yaml "${kube_flags[@]}"
50 | - kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx:'
51 | - kube::test::get_object_assert deployment "{{range.items}}{{${image_field0:?}}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
52 | - # Command
53 | - output_message=$(kubectl convert --local -f hack/testdata/deployment-revision1.yaml --output-version=extensions/v1beta1 -o yaml "${kube_flags[@]}")
54 | - # Post-condition: apiVersion is still apps/v1 in the live deployment, but command output is the new value
55 | - kube::test::get_object_assert 'deployment nginx' "{{ .apiVersion }}" 'apps/v1'
56 | - kube::test::if_has_string "${output_message}" "extensions/v1beta1"
57 | - # Clean up
58 | - kubectl delete deployment nginx "${kube_flags[@]}"
59 | -
60 | - ## Convert multiple busybox PODs recursively from directory of YAML files
61 | - # Pre-condition: only busybox0 & busybox1 PODs exist
62 | - kube::test::wait_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
63 | - # Command
64 | - output_message=$(! kubectl convert -f hack/testdata/recursive/pod --recursive 2>&1 "${kube_flags[@]}")
65 | - # Post-condition: busybox0 & busybox1 PODs are converted, and since busybox2 is malformed, it should error
66 | - kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
67 | - kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
68 | -
69 | ## Get multiple busybox PODs recursively from directory of YAML files
70 | # Pre-condition: busybox0 & busybox1 PODs exist
71 | kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
72 | @@ -389,11 +363,11 @@ run_recursive_resources_tests() {
73 | # Create deployments (revision 1) recursively from directory of YAML files
74 | ! kubectl create -f hack/testdata/recursive/deployment --recursive "${kube_flags[@]}" || exit 1
75 | kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx0-deployment:nginx1-deployment:'
76 | - kube::test::get_object_assert deployment "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_NGINX}:${IMAGE_NGINX}:"
77 | + kube::test::get_object_assert deployment "{{range.items}}{{${image_field0:?}}}:{{end}}" "${IMAGE_NGINX}:${IMAGE_NGINX}:"
78 | ## Rollback the deployments to revision 1 recursively
79 | output_message=$(! kubectl rollout undo -f hack/testdata/recursive/deployment --recursive --to-revision=1 2>&1 "${kube_flags[@]}")
80 | # Post-condition: nginx0 & nginx1 should be a no-op, and since nginx2 is malformed, it should error
81 | - kube::test::get_object_assert deployment "{{range.items}}{{$image_field0}}:{{end}}" "${IMAGE_NGINX}:${IMAGE_NGINX}:"
82 | + kube::test::get_object_assert deployment "{{range.items}}{{${image_field0:?}}}:{{end}}" "${IMAGE_NGINX}:${IMAGE_NGINX}:"
83 | kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
84 | ## Pause the deployments recursively
85 | # shellcheck disable=SC2034 # PRESERVE_ERR_FILE is used in kubectl-with-retry
86 | diff --git a/test/cmd/template-output.sh b/test/cmd/template-output.sh
87 | index b5e9fff2e27..3155077b947 100755
88 | --- a/test/cmd/template-output.sh
89 | +++ b/test/cmd/template-output.sh
90 | @@ -62,10 +62,6 @@ run_template_output_tests() {
91 | output_message=$(kubectl "${kube_flags[@]:?}" expose -f hack/testdata/redis-slave-replicaset.yaml --save-config --port=80 --target-port=8000 --dry-run=client --template="{{ .metadata.name }}:")
92 | kube::test::if_has_string "${output_message}" 'redis-slave:'
93 |
94 | - # check that convert command supports --template output
95 | - output_message=$(kubectl convert "${kube_flags[@]:?}" -f hack/testdata/deployment-revision1.yaml --output-version=apps/v1beta1 --template="{{ .metadata.name }}:")
96 | - kube::test::if_has_string "${output_message}" 'nginx:'
97 | -
98 | # check that run command supports --template output
99 | output_message=$(kubectl "${kube_flags[@]:?}" run --dry-run=client --template="{{ .metadata.name }}:" pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)')
100 | kube::test::if_has_string "${output_message}" 'pi:'
101 |
--------------------------------------------------------------------------------
/patches/fix-missing-env-91500.1.18.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: David Eads
3 | Date: Wed, 27 May 2020 11:44:14 -0400
4 | Subject: [PATCH] reduce race risk in kubelet for missing
5 | KUBERNETES_SERVICE_HOST
6 |
7 | ---
8 | pkg/kubelet/kubelet.go | 19 +++-
9 | pkg/kubelet/kubelet_pods.go | 12 +++
10 | pkg/kubelet/kubelet_pods_test.go | 153 +++++++++++++++++++------------
11 | pkg/kubelet/kubelet_test.go | 1 +
12 | 4 files changed, 122 insertions(+), 63 deletions(-)
13 |
14 | diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go
15 | index 1d571c33b07..919629b3709 100644
16 | --- a/pkg/kubelet/kubelet.go
17 | +++ b/pkg/kubelet/kubelet.go
18 | @@ -530,13 +530,18 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
19 | PodCgroupRoot: kubeDeps.ContainerManager.GetPodCgroupRoot(),
20 | }
21 |
22 | - serviceIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
23 | + var serviceLister corelisters.ServiceLister
24 | + var serviceHasSynced cache.InformerSynced
25 | if kubeDeps.KubeClient != nil {
26 | - serviceLW := cache.NewListWatchFromClient(kubeDeps.KubeClient.CoreV1().RESTClient(), "services", metav1.NamespaceAll, fields.Everything())
27 | - r := cache.NewReflector(serviceLW, &v1.Service{}, serviceIndexer, 0)
28 | - go r.Run(wait.NeverStop)
29 | + kubeInformers := informers.NewSharedInformerFactory(kubeDeps.KubeClient, 0)
30 | + serviceLister = kubeInformers.Core().V1().Services().Lister()
31 | + serviceHasSynced = kubeInformers.Core().V1().Services().Informer().HasSynced
32 | + kubeInformers.Start(wait.NeverStop)
33 | + } else {
34 | + serviceIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
35 | + serviceLister = corelisters.NewServiceLister(serviceIndexer)
36 | + serviceHasSynced = func() bool { return true }
37 | }
38 | - serviceLister := corelisters.NewServiceLister(serviceIndexer)
39 |
40 | // TODO: get the real node object of ourself,
41 | // and use the real node name and UID.
42 | @@ -587,6 +592,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
43 | registerSchedulable: registerSchedulable,
44 | dnsConfigurer: dns.NewConfigurer(kubeDeps.Recorder, nodeRef, parsedNodeIP, clusterDNS, kubeCfg.ClusterDomain, kubeCfg.ResolverConfig),
45 | serviceLister: serviceLister,
46 | + serviceHasSynced: serviceHasSynced,
47 | nodeLister: nodeLister,
48 | nodeHasSynced: nodeHasSynced,
49 | masterServiceNamespace: masterServiceNamespace,
50 | @@ -976,6 +982,9 @@ type Kubelet struct {
51 | masterServiceNamespace string
52 | // serviceLister knows how to list services
53 | serviceLister serviceLister
54 | + // serviceHasSynced indicates whether services have been sync'd at least once.
55 | + // Check this before trusting a response from the lister.
56 | + serviceHasSynced cache.InformerSynced
57 | // nodeLister knows how to list nodes
58 | nodeLister corelisters.NodeLister
59 | // nodeHasSynced indicates whether nodes have been sync'd at least once.
60 | diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go
61 | index 65a9fd74627..4feff10400d 100644
62 | --- a/pkg/kubelet/kubelet_pods.go
63 | +++ b/pkg/kubelet/kubelet_pods.go
64 | @@ -567,6 +567,18 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *v1.Pod, container *v1.Container
65 | return nil, fmt.Errorf("nil pod.spec.enableServiceLinks encountered, cannot construct envvars")
66 | }
67 |
68 | + // If the pod originates from the kube-api, when we know that the kube-apiserver is responding and the kubelet's credentials are valid.
69 | + // Knowing this, it is reasonable to wait until the service lister has synchronized at least once before attempting to build
70 | + // a service env var map. This doesn't present the race below from happening entirely, but it does prevent the "obvious"
71 | + // failure case of services simply not having completed a list operation that can reasonably be expected to succeed.
72 | + // One common case this prevents is a kubelet restart reading pods before services and some pod not having the
73 | + // KUBERNETES_SERVICE_HOST injected because we didn't wait a short time for services to sync before proceeding.
74 | + // The KUBERNETES_SERVICE_HOST link is special because it is unconditionally injected into pods and is read by the
75 | + // in-cluster-config for pod clients
76 | + if !kubetypes.IsStaticPod(pod) && !kl.serviceHasSynced() {
77 | + return nil, fmt.Errorf("services have not yet been read at least once, cannot construct envvars")
78 | + }
79 | +
80 | var result []kubecontainer.EnvVar
81 | // Note: These are added to the docker Config, but are not included in the checksum computed
82 | // by kubecontainer.HashContainer(...). That way, we can still determine whether an
83 | diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go
84 | index a542845c46e..190a9f6af41 100644
85 | --- a/pkg/kubelet/kubelet_pods_test.go
86 | +++ b/pkg/kubelet/kubelet_pods_test.go
87 | @@ -48,6 +48,7 @@ import (
88 | containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
89 | "k8s.io/kubernetes/pkg/kubelet/server/portforward"
90 | "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
91 | + kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
92 | "k8s.io/kubernetes/pkg/volume/util/hostutil"
93 | "k8s.io/kubernetes/pkg/volume/util/subpath"
94 | )
95 | @@ -454,12 +455,36 @@ func TestMakeEnvironmentVariables(t *testing.T) {
96 | container *v1.Container // the container to use
97 | masterServiceNs string // the namespace to read master service info from
98 | nilLister bool // whether the lister should be nil
99 | + staticPod bool // whether the pod should be a static pod (versus an API pod)
100 | + unsyncedServices bool // whether the services should NOT be synced
101 | configMap *v1.ConfigMap // an optional ConfigMap to pull from
102 | secret *v1.Secret // an optional Secret to pull from
103 | expectedEnvs []kubecontainer.EnvVar // a set of expected environment vars
104 | expectedError bool // does the test fail
105 | expectedEvent string // does the test emit an event
106 | }{
107 | + {
108 | + name: "if services aren't synced, non-static pods should fail",
109 | + ns: "test1",
110 | + enableServiceLinks: &falseValue,
111 | + container: &v1.Container{Env: []v1.EnvVar{}},
112 | + masterServiceNs: metav1.NamespaceDefault,
113 | + nilLister: false,
114 | + staticPod: false,
115 | + unsyncedServices: true,
116 | + expectedEnvs: []kubecontainer.EnvVar{},
117 | + expectedError: true,
118 | + },
119 | + {
120 | + name: "if services aren't synced, static pods should succeed", // if there is no service
121 | + ns: "test1",
122 | + enableServiceLinks: &falseValue,
123 | + container: &v1.Container{Env: []v1.EnvVar{}},
124 | + masterServiceNs: metav1.NamespaceDefault,
125 | + nilLister: false,
126 | + staticPod: true,
127 | + unsyncedServices: true,
128 | + },
129 | {
130 | name: "api server = Y, kubelet = Y",
131 | ns: "test1",
132 | @@ -1606,71 +1631,83 @@ func TestMakeEnvironmentVariables(t *testing.T) {
133 | }
134 |
135 | for _, tc := range testCases {
136 | - fakeRecorder := record.NewFakeRecorder(1)
137 | - testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
138 | - testKubelet.kubelet.recorder = fakeRecorder
139 | - defer testKubelet.Cleanup()
140 | - kl := testKubelet.kubelet
141 | - kl.masterServiceNamespace = tc.masterServiceNs
142 | - if tc.nilLister {
143 | - kl.serviceLister = nil
144 | - } else {
145 | - kl.serviceLister = testServiceLister{services}
146 | - }
147 | + t.Run(tc.name, func(t *testing.T) {
148 | + fakeRecorder := record.NewFakeRecorder(1)
149 | + testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
150 | + testKubelet.kubelet.recorder = fakeRecorder
151 | + defer testKubelet.Cleanup()
152 | + kl := testKubelet.kubelet
153 | + kl.masterServiceNamespace = tc.masterServiceNs
154 | + if tc.nilLister {
155 | + kl.serviceLister = nil
156 | + } else if tc.unsyncedServices {
157 | + kl.serviceLister = testServiceLister{}
158 | + kl.serviceHasSynced = func() bool { return false }
159 | + } else {
160 | + kl.serviceLister = testServiceLister{services}
161 | + kl.serviceHasSynced = func() bool { return true }
162 | + }
163 | +
164 | + testKubelet.fakeKubeClient.AddReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) {
165 | + var err error
166 | + if tc.configMap == nil {
167 | + err = apierrors.NewNotFound(action.GetResource().GroupResource(), "configmap-name")
168 | + }
169 | + return true, tc.configMap, err
170 | + })
171 | + testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
172 | + var err error
173 | + if tc.secret == nil {
174 | + err = apierrors.NewNotFound(action.GetResource().GroupResource(), "secret-name")
175 | + }
176 | + return true, tc.secret, err
177 | + })
178 | +
179 | + testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
180 | + var err error
181 | + if tc.secret == nil {
182 | + err = errors.New("no secret defined")
183 | + }
184 | + return true, tc.secret, err
185 | + })
186 |
187 | - testKubelet.fakeKubeClient.AddReactor("get", "configmaps", func(action core.Action) (bool, runtime.Object, error) {
188 | - var err error
189 | - if tc.configMap == nil {
190 | - err = apierrors.NewNotFound(action.GetResource().GroupResource(), "configmap-name")
191 | + testPod := &v1.Pod{
192 | + ObjectMeta: metav1.ObjectMeta{
193 | + Namespace: tc.ns,
194 | + Name: "dapi-test-pod-name",
195 | + Annotations: map[string]string{},
196 | + },
197 | + Spec: v1.PodSpec{
198 | + ServiceAccountName: "special",
199 | + NodeName: "node-name",
200 | + EnableServiceLinks: tc.enableServiceLinks,
201 | + },
202 | }
203 | - return true, tc.configMap, err
204 | - })
205 | - testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
206 | - var err error
207 | - if tc.secret == nil {
208 | - err = apierrors.NewNotFound(action.GetResource().GroupResource(), "secret-name")
209 | + podIP := "1.2.3.4"
210 | + podIPs := []string{"1.2.3.4,fd00::6"}
211 | + if tc.staticPod {
212 | + testPod.Annotations[kubetypes.ConfigSourceAnnotationKey] = "file"
213 | }
214 | - return true, tc.secret, err
215 | - })
216 |
217 | - testKubelet.fakeKubeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
218 | - var err error
219 | - if tc.secret == nil {
220 | - err = errors.New("no secret defined")
221 | + t.Logf("makeEnvironmentVariables testPod %v; container: %v; pod IP: %v; pod IPs: %v.", testPod, tc.container, podIP, podIPs)
222 | + result, err := kl.makeEnvironmentVariables(testPod, tc.container, podIP, podIPs)
223 | + select {
224 | + case e := <-fakeRecorder.Events:
225 | + assert.Equal(t, tc.expectedEvent, e)
226 | + default:
227 | + assert.Equal(t, "", tc.expectedEvent)
228 | + }
229 | + if tc.expectedError {
230 | + assert.Error(t, err, tc.name)
231 | + } else {
232 | + assert.NoError(t, err, "[%s]", tc.name)
233 | +
234 | + sort.Sort(envs(result))
235 | + sort.Sort(envs(tc.expectedEnvs))
236 | + assert.Equal(t, tc.expectedEnvs, result, "[%s] env entries", tc.name)
237 | }
238 | - return true, tc.secret, err
239 | })
240 |
241 | - testPod := &v1.Pod{
242 | - ObjectMeta: metav1.ObjectMeta{
243 | - Namespace: tc.ns,
244 | - Name: "dapi-test-pod-name",
245 | - },
246 | - Spec: v1.PodSpec{
247 | - ServiceAccountName: "special",
248 | - NodeName: "node-name",
249 | - EnableServiceLinks: tc.enableServiceLinks,
250 | - },
251 | - }
252 | - podIP := "1.2.3.4"
253 | - podIPs := []string{"1.2.3.4,fd00::6"}
254 | -
255 | - result, err := kl.makeEnvironmentVariables(testPod, tc.container, podIP, podIPs)
256 | - select {
257 | - case e := <-fakeRecorder.Events:
258 | - assert.Equal(t, tc.expectedEvent, e)
259 | - default:
260 | - assert.Equal(t, "", tc.expectedEvent)
261 | - }
262 | - if tc.expectedError {
263 | - assert.Error(t, err, tc.name)
264 | - } else {
265 | - assert.NoError(t, err, "[%s]", tc.name)
266 | -
267 | - sort.Sort(envs(result))
268 | - sort.Sort(envs(tc.expectedEnvs))
269 | - assert.Equal(t, tc.expectedEnvs, result, "[%s] env entries", tc.name)
270 | - }
271 | }
272 | }
273 |
274 | diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go
275 | index 748a92463ce..9da1566fe89 100644
276 | --- a/pkg/kubelet/kubelet_test.go
277 | +++ b/pkg/kubelet/kubelet_test.go
278 | @@ -180,6 +180,7 @@ func newTestKubeletWithImageList(
279 | kubelet.sourcesReady = config.NewSourcesReady(func(_ sets.String) bool { return true })
280 | kubelet.masterServiceNamespace = metav1.NamespaceDefault
281 | kubelet.serviceLister = testServiceLister{}
282 | + kubelet.serviceHasSynced = func() bool { return true }
283 | kubelet.nodeHasSynced = func() bool { return true }
284 | kubelet.nodeLister = testNodeLister{
285 | nodes: []*v1.Node{
286 |
--------------------------------------------------------------------------------
/patches/fix-run-docker.1.24.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Tue, 27 Jul 2021 16:43:27 +0800
4 | Subject: [PATCH 1/2] Run docker as root in tests
5 |
6 | ---
7 | build/common.sh | 2 +-
8 | 1 file changed, 1 insertion(+), 1 deletion(-)
9 |
10 | diff --git a/build/common.sh b/build/common.sh
11 | index 257d36b2fa7..96852d940f2 100755
12 | --- a/build/common.sh
13 | +++ b/build/common.sh
14 | @@ -490,7 +490,7 @@ function kube::build::run_build_command_ex() {
15 |
16 | local -a docker_run_opts=(
17 | "--name=${container_name}"
18 | - "--user=$(id -u):$(id -g)"
19 | + "--user=root"
20 | "--hostname=${HOSTNAME}"
21 | "${DOCKER_MOUNT_ARGS[@]}"
22 | )
23 |
24 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
25 | From: Shiming Zhang
26 | Date: Wed, 28 Jul 2021 17:37:59 +0800
27 | Subject: [PATCH 2/2] Run docker with device kmsg
28 |
29 | ---
30 | build/common.sh | 1 +
31 | 1 file changed, 1 insertion(+)
32 |
33 | diff --git a/build/common.sh b/build/common.sh
34 | index 96852d940f2..48998f4a21a 100755
35 | --- a/build/common.sh
36 | +++ b/build/common.sh
37 | @@ -492,6 +492,7 @@ function kube::build::run_build_command_ex() {
38 | "--name=${container_name}"
39 | "--user=root"
40 | "--hostname=${HOSTNAME}"
41 | + "--device=/dev/kmsg"
42 | "${DOCKER_MOUNT_ARGS[@]}"
43 | )
44 |
45 |
--------------------------------------------------------------------------------
/patches/fix-test.1.16.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Tue, 27 Jul 2021 15:17:40 +0800
4 | Subject: [PATCH] Fix test
5 |
6 | ---
7 | .../pkg/apis/apiextensions/helpers_test.go | 2 +-
8 | 1 file changed, 1 insertion(+), 1 deletion(-)
9 |
10 | diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go
11 | index fbbebee6060..7acffd7eb76 100644
12 | --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go
13 | +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go
14 | @@ -275,7 +275,7 @@ func TestSetCRDCondition(t *testing.T) {
15 | t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
16 | }
17 | if crd.Status.Conditions[i].LastTransitionTime.IsZero() {
18 | - t.Errorf("%q lastTransitionTime should not be null: %v", tc.name, i, crd.Status.Conditions)
19 | + t.Errorf("%q lastTransitionTime should not be null: %v", tc.name, crd.Status.Conditions)
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/patches/no-delete-images.1.10.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Thu, 22 Jul 2021 18:41:45 +0800
4 | Subject: [PATCH] No delete images
5 |
6 | ---
7 | build/lib/release.sh | 8 ++++----
8 | 1 file changed, 4 insertions(+), 4 deletions(-)
9 |
10 | diff --git a/build/lib/release.sh b/build/lib/release.sh
11 | index b0a45b4e620..3af72ecd26e 100644
12 | --- a/build/lib/release.sh
13 | +++ b/build/lib/release.sh
14 | @@ -374,11 +374,11 @@ function kube::release::create_docker_images_for_server() {
15 | "${DOCKER[@]}" rmi "${release_docker_image_tag}" 2>/dev/null || true
16 | "${DOCKER[@]}" tag "${docker_image_tag}" "${release_docker_image_tag}" 2>/dev/null
17 | fi
18 | - else
19 | + # else
20 | # not a release
21 | - kube::log::status "Deleting docker image ${docker_image_tag}"
22 | - "${DOCKER[@]}" rmi ${docker_image_tag} &>/dev/null || true
23 | - "${DOCKER[@]}" rmi ${deprecated_image_tag} &>/dev/null || true
24 | + # kube::log::status "Deleting docker image ${docker_image_tag}"
25 | + # "${DOCKER[@]}" rmi ${docker_image_tag} &>/dev/null || true
26 | + # "${DOCKER[@]}" rmi ${deprecated_image_tag} &>/dev/null || true
27 | fi
28 | ) &
29 | done
30 |
--------------------------------------------------------------------------------
/patches/no-delete-images.1.12.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Thu, 22 Jul 2021 18:41:45 +0800
4 | Subject: [PATCH] No delete images
5 |
6 | ---
7 | build/lib/release.sh | 8 ++++----
8 | 1 file changed, 4 insertions(+), 4 deletions(-)
9 |
10 | diff --git a/build/lib/release.sh b/build/lib/release.sh
11 | index 1275e6e1d96..ef7a5838e73 100644
12 | --- a/build/lib/release.sh
13 | +++ b/build/lib/release.sh
14 | @@ -374,11 +374,11 @@ function kube::release::create_docker_images_for_server() {
15 | "${DOCKER[@]}" rmi "${release_docker_image_tag}" 2>/dev/null || true
16 | "${DOCKER[@]}" tag "${docker_image_tag}" "${release_docker_image_tag}" 2>/dev/null
17 | fi
18 | - else
19 | + # else
20 | # not a release
21 | - kube::log::status "Deleting docker image ${docker_image_tag}"
22 | - "${DOCKER[@]}" rmi "${docker_image_tag}" &>/dev/null || true
23 | - "${DOCKER[@]}" rmi "${deprecated_image_tag}" &>/dev/null || true
24 | + # kube::log::status "Deleting docker image ${docker_image_tag}"
25 | + # "${DOCKER[@]}" rmi "${docker_image_tag}" &>/dev/null || true
26 | + # "${DOCKER[@]}" rmi "${deprecated_image_tag}" &>/dev/null || true
27 | fi
28 | ) &
29 | done
30 |
--------------------------------------------------------------------------------
/patches/no-delete-images.1.15.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Thu, 22 Jul 2021 18:41:45 +0800
4 | Subject: [PATCH] No delete images
5 |
6 | ---
7 | build/lib/release.sh | 6 +++---
8 | 1 file changed, 3 insertions(+), 3 deletions(-)
9 |
10 | diff --git a/build/lib/release.sh b/build/lib/release.sh
11 | index 9e0de70ffe5..b28c38fcb56 100644
12 | --- a/build/lib/release.sh
13 | +++ b/build/lib/release.sh
14 | @@ -408,10 +408,10 @@ EOF
15 | "${DOCKER[@]}" rmi "${release_docker_image_tag}" 2>/dev/null || true
16 | "${DOCKER[@]}" tag "${docker_image_tag}" "${release_docker_image_tag}" 2>/dev/null
17 | fi
18 | - else
19 | + # else
20 | # not a release
21 | - kube::log::status "Deleting docker image ${docker_image_tag}"
22 | - "${DOCKER[@]}" rmi "${docker_image_tag}" &>/dev/null || true
23 | + # kube::log::status "Deleting docker image ${docker_image_tag}"
24 | + # "${DOCKER[@]}" rmi "${docker_image_tag}" &>/dev/null || true
25 | fi
26 | ) &
27 | done
28 |
--------------------------------------------------------------------------------
/patches/no-delete-images.1.24.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Thu, 22 Jul 2021 18:41:45 +0800
4 | Subject: [PATCH] No delete images
5 |
6 | ---
7 | build/lib/release.sh | 4 ++--
8 | 1 file changed, 2 insertions(+), 2 deletions(-)
9 |
10 | diff --git a/build/lib/release.sh b/build/lib/release.sh
11 | index ef262b5ed04..2130f1e239a 100644
12 | --- a/build/lib/release.sh
13 | +++ b/build/lib/release.sh
14 | @@ -364,8 +364,8 @@ function kube::release::create_docker_images_for_server() {
15 | rm -rf "${docker_build_path}"
16 | ln "${binary_file_path}.tar" "${images_dir}/"
17 |
18 | - kube::log::status "Deleting docker image ${docker_image_tag}"
19 | - "${DOCKER[@]}" rmi "${docker_image_tag}" &>/dev/null || true
20 | + # kube::log::status "Deleting docker image ${docker_image_tag}"
21 | + # "${DOCKER[@]}" rmi "${docker_image_tag}" &>/dev/null || true
22 | ) &
23 | done
24 |
25 |
--------------------------------------------------------------------------------
/patches/nokmem.1.13.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Tue, 17 Aug 2021 10:00:45 +0800
4 | Subject: [PATCH] Disabled kmem
5 |
6 | ---
7 | .../runc/libcontainer/cgroups/fs/memory.go | 42 ++-----------------
8 | 1 file changed, 4 insertions(+), 38 deletions(-)
9 |
10 | diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
11 | index ad395a5d621..72db8679687 100644
12 | --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
13 | +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go
14 | @@ -4,24 +4,20 @@ package fs
15 |
16 | import (
17 | "bufio"
18 | + "errors"
19 | "fmt"
20 | - "io/ioutil"
21 | "os"
22 | "path/filepath"
23 | "strconv"
24 | "strings"
25 | - "syscall" // only for Errno
26 |
27 | "github.com/opencontainers/runc/libcontainer/cgroups"
28 | "github.com/opencontainers/runc/libcontainer/configs"
29 | -
30 | - "golang.org/x/sys/unix"
31 | )
32 |
33 | const (
34 | - cgroupKernelMemoryLimit = "memory.kmem.limit_in_bytes"
35 | - cgroupMemorySwapLimit = "memory.memsw.limit_in_bytes"
36 | - cgroupMemoryLimit = "memory.limit_in_bytes"
37 | + cgroupMemorySwapLimit = "memory.memsw.limit_in_bytes"
38 | + cgroupMemoryLimit = "memory.limit_in_bytes"
39 | )
40 |
41 | type MemoryGroup struct {
42 | @@ -68,41 +64,11 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
43 | }
44 |
45 | func EnableKernelMemoryAccounting(path string) error {
46 | - // Check if kernel memory is enabled
47 | - // We have to limit the kernel memory here as it won't be accounted at all
48 | - // until a limit is set on the cgroup and limit cannot be set once the
49 | - // cgroup has children, or if there are already tasks in the cgroup.
50 | - for _, i := range []int64{1, -1} {
51 | - if err := setKernelMemory(path, i); err != nil {
52 | - return err
53 | - }
54 | - }
55 | return nil
56 | }
57 |
58 | func setKernelMemory(path string, kernelMemoryLimit int64) error {
59 | - if path == "" {
60 | - return fmt.Errorf("no such directory for %s", cgroupKernelMemoryLimit)
61 | - }
62 | - if !cgroups.PathExists(filepath.Join(path, cgroupKernelMemoryLimit)) {
63 | - // kernel memory is not enabled on the system so we should do nothing
64 | - return nil
65 | - }
66 | - if err := ioutil.WriteFile(filepath.Join(path, cgroupKernelMemoryLimit), []byte(strconv.FormatInt(kernelMemoryLimit, 10)), 0700); err != nil {
67 | - // Check if the error number returned by the syscall is "EBUSY"
68 | - // The EBUSY signal is returned on attempts to write to the
69 | - // memory.kmem.limit_in_bytes file if the cgroup has children or
70 | - // once tasks have been attached to the cgroup
71 | - if pathErr, ok := err.(*os.PathError); ok {
72 | - if errNo, ok := pathErr.Err.(syscall.Errno); ok {
73 | - if errNo == unix.EBUSY {
74 | - return fmt.Errorf("failed to set %s, because either tasks have already joined this cgroup or it has children", cgroupKernelMemoryLimit)
75 | - }
76 | - }
77 | - }
78 | - return fmt.Errorf("failed to write %v to %v: %v", kernelMemoryLimit, cgroupKernelMemoryLimit, err)
79 | - }
80 | - return nil
81 | + return errors.New("kernel memory accounting disabled in this runc build")
82 | }
83 |
84 | func setMemoryAndSwap(path string, cgroup *configs.Cgroup) error {
85 |
--------------------------------------------------------------------------------
/patches/nokmem.1.20.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: Shiming Zhang
3 | Date: Mon, 16 Aug 2021 19:14:44 +0800
4 | Subject: [PATCH] Disabled kmem
5 |
6 | ---
7 | .../opencontainers/runc/libcontainer/cgroups/fs/kmem.go | 2 +-
8 | .../runc/libcontainer/cgroups/fs/kmem_disabled.go | 2 +-
9 | 2 files changed, 2 insertions(+), 2 deletions(-)
10 |
11 | diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem.go
12 | index 8d97a6791a4..8935e811742 100644
13 | --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem.go
14 | +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem.go
15 | @@ -1,4 +1,4 @@
16 | -// +build linux,!nokmem
17 | +// +build linux,ignore
18 |
19 | package fs
20 |
21 | diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem_disabled.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem_disabled.go
22 | index ac290fd7a02..c8fbdaa3128 100644
23 | --- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem_disabled.go
24 | +++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/kmem_disabled.go
25 | @@ -1,4 +1,4 @@
26 | -// +build linux,nokmem
27 | +// +build linux
28 |
29 | package fs
30 |
31 |
--------------------------------------------------------------------------------
/patches/update-kube-proxy-iptables.1.18.patch:
--------------------------------------------------------------------------------
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 | From: cyclinder
3 | Date: Fri, 22 Dec 2023 14:23:10 +0800
4 | Subject: [PATCH] kube-proxy: update iptables version
5 |
6 | ---
7 | build/BUILD | 2 +-
8 | build/common.sh | 4 ++--
9 | 2 files changed, 3 insertions(+), 3 deletions(-)
10 |
11 | diff --git a/build/BUILD b/build/BUILD
12 | index 70e3874b441..4c67a178517 100644
13 | --- a/build/BUILD
14 | +++ b/build/BUILD
15 | @@ -42,7 +42,7 @@ DOCKERIZED_BINARIES = {
16 | "target": "//cmd/kube-scheduler:kube-scheduler",
17 | },
18 | "kube-proxy": {
19 | - "base": "@debian-iptables-{ARCH}//image",
20 | + "base": "@distroless-iptables//image",
21 | "target": "//cmd/kube-proxy:kube-proxy",
22 | },
23 | }
24 | diff --git a/build/common.sh b/build/common.sh
25 | index 9cd95b5af51..13c15466c39 100755
26 | --- a/build/common.sh
27 | +++ b/build/common.sh
28 | @@ -95,14 +95,14 @@ readonly KUBE_CONTAINER_RSYNC_PORT=8730
29 | kube::build::get_docker_wrapped_binaries() {
30 | local arch=$1
31 | local debian_base_version=v2.1.3
32 | - local debian_iptables_version=v12.1.2
33 | + local distroless_iptables_version=v0.4.2
34 | ### If you change any of these lists, please also update DOCKERIZED_BINARIES
35 | ### in build/BUILD. And kube::golang::server_image_targets
36 | local targets=(
37 | "kube-apiserver,${KUBE_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
38 | "kube-controller-manager,${KUBE_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
39 | "kube-scheduler,${KUBE_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
40 | - "kube-proxy,${KUBE_BASE_IMAGE_REGISTRY}/debian-iptables-${arch}:${debian_iptables_version}"
41 | + "kube-proxy,registry.k8s.io/build-image/distroless-iptables:${distroless_iptables_version}"
42 | )
43 |
44 | echo "${targets[@]}"
45 |
--------------------------------------------------------------------------------
/rpm/kubeadm/10-kubeadm.conf:
--------------------------------------------------------------------------------
1 | # Note: This dropin only works with kubeadm and kubelet v1.11+
2 | [Service]
3 | Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
4 | Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
5 | # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
6 | EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
7 | # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
8 | # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
9 | EnvironmentFile=-/etc/sysconfig/kubelet
10 | ExecStart=
11 | ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
12 |
--------------------------------------------------------------------------------
/rpm/kubeadm/kubeadm.spec:
--------------------------------------------------------------------------------
1 | Name: kubeadm
2 | Version: %{_version}
3 | Release: %{_release}
4 | Summary: Command-line utility for administering a Kubernetes cluster.
5 | License: ASL 2.0
6 |
7 | URL: https://kubernetes.io
8 | Source0: %{name}-%{version}.tar.gz
9 |
10 | BuildRequires: systemd
11 |
12 | Requires: kubelet >= %{_version}
13 | Requires: kubectl >= %{_version}
14 | Requires: kubernetes-cni >= 0.8.6
15 | Requires: cri-tools >= 1.13.0
16 |
17 | %description
18 | Command-line utility for administering a Kubernetes cluster.
19 |
20 | %prep
21 | %setup
22 |
23 | install -m 755 -d %{buildroot}%{_sysconfdir}/kubernetes/manifests/
24 | install -m 755 -d %{buildroot}%{_unitdir}/kubelet.service.d/
25 | install -m 755 -d %{buildroot}%{_bindir}
26 | install -p -m 755 -t %{buildroot}%{_bindir}/ kubeadm
27 | install -p -m 644 -t %{buildroot}%{_unitdir}/kubelet.service.d/ 10-kubeadm.conf
28 |
29 | %files
30 | %{_bindir}/kubeadm
31 | %{_unitdir}/kubelet.service.d/10-kubeadm.conf
32 |
--------------------------------------------------------------------------------
/rpm/kubectl/kubectl.spec:
--------------------------------------------------------------------------------
1 | Name: kubectl
2 | Version: %{_version}
3 | Release: %{_release}
4 | Summary: Command-line utility for interacting with a Kubernetes cluster.
5 | License: ASL 2.0
6 |
7 | URL: https://kubernetes.io
8 | Source0: %{name}-%{version}.tar.gz
9 |
10 | BuildRequires: systemd
11 |
12 | %description
13 | Command-line utility for interacting with a Kubernetes cluster.
14 |
15 | %prep
16 | %setup
17 |
18 | install -m 755 -d %{buildroot}%{_bindir}
19 | install -p -m 755 -t %{buildroot}%{_bindir}/ kubectl
20 |
21 | %files
22 | %{_bindir}/kubectl
23 |
--------------------------------------------------------------------------------
/rpm/kubelet/kubelet.env:
--------------------------------------------------------------------------------
1 | KUBELET_EXTRA_ARGS=
2 |
--------------------------------------------------------------------------------
/rpm/kubelet/kubelet.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=kubelet: The Kubernetes Node Agent
3 | Documentation=https://kubernetes.io/docs/
4 | Wants=network-online.target
5 | After=network-online.target
6 |
7 | [Service]
8 | ExecStart=/usr/bin/kubelet
9 | Restart=always
10 | StartLimitInterval=0
11 | RestartSec=10
12 |
13 | [Install]
14 | WantedBy=multi-user.target
15 |
--------------------------------------------------------------------------------
/rpm/kubelet/kubelet.spec:
--------------------------------------------------------------------------------
1 | Name: kubelet
2 | Version: %{_version}
3 | Release: %{_release}
4 | Summary: Container cluster management
5 | License: ASL 2.0
6 |
7 | URL: https://kubernetes.io
8 | Source0: %{name}-%{version}.tar.gz
9 |
10 | BuildRequires: systemd
11 |
12 | Requires: iptables >= 1.4.21
13 | Requires: kubernetes-cni >= 0.8.6
14 | Requires: socat
15 | Requires: util-linux
16 | Requires: ethtool
17 | Requires: iproute
18 | Requires: ebtables
19 | Requires: conntrack
20 |
21 | %description
22 | The node agent of Kubernetes, the container cluster manager.
23 |
24 | %prep
25 | %setup
26 |
27 | install -m 755 -d %{buildroot}%{_unitdir}
28 | install -m 755 -d %{buildroot}%{_unitdir}/kubelet.service.d/
29 | install -m 755 -d %{buildroot}%{_bindir}
30 | install -m 755 -d %{buildroot}/var/lib/kubelet/
31 | install -p -m 755 -t %{buildroot}%{_bindir}/ kubelet
32 | install -p -m 644 -t %{buildroot}%{_unitdir}/ kubelet.service
33 | install -m 755 -d %{buildroot}%{_sysconfdir}/sysconfig/
34 | install -p -m 644 -T kubelet.env %{buildroot}%{_sysconfdir}/sysconfig/kubelet
35 |
36 |
37 |
38 | %files
39 | %{_bindir}/kubelet
40 | %{_unitdir}/kubelet.service
41 |
42 | %config(noreplace) %{_sysconfdir}/sysconfig/kubelet
43 |
--------------------------------------------------------------------------------