Skip to content

Commit 854dac6

Browse files
authored
Merge pull request #1 from oracle-devrel/feature-init
Initial commit
2 parents 51bb246 + 22fdb82 commit 854dac6

File tree

17 files changed

+488
-25
lines changed

17 files changed

+488
-25
lines changed

.gitignore

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
# Created by https://www.toptal.com/developers/gitignore/api/macos,go,visualstudiocode
2+
# Edit at https://www.toptal.com/developers/gitignore?templates=macos,go,visualstudiocode
3+
4+
### Go ###
5+
# If you prefer the allow list template instead of the deny list, see community template:
6+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
7+
#
8+
# Binaries for programs and plugins
9+
*.exe
10+
*.exe~
11+
*.dll
12+
*.so
13+
*.dylib
14+
15+
# Test binary, built with `go test -c`
16+
*.test
17+
18+
# Output of the go coverage tool, specifically when used with LiteIDE
19+
*.out
20+
21+
# Dependency directories (remove the comment below to include it)
22+
# vendor/
23+
24+
# Go workspace file
25+
go.work
26+
27+
### macOS ###
128
# General
229
.DS_Store
330
.AppleDouble
@@ -26,8 +53,27 @@ Network Trash Folder
2653
Temporary Items
2754
.apdisk
2855

29-
# ignore common security keys
30-
.key
31-
.crt
32-
.csr
33-
.pem
56+
### macOS Patch ###
57+
# iCloud generated files
58+
*.icloud
59+
60+
### VisualStudioCode ###
61+
.vscode/*
62+
!.vscode/settings.json
63+
!.vscode/tasks.json
64+
!.vscode/launch.json
65+
!.vscode/extensions.json
66+
!.vscode/*.code-snippets
67+
68+
# Local History for Visual Studio Code
69+
.history/
70+
71+
# Built Visual Studio Code Extensions
72+
*.vsix
73+
74+
### VisualStudioCode Patch ###
75+
# Ignore all local history of files
76+
.history
77+
.ionide
78+
79+
# End of https://www.toptal.com/developers/gitignore/api/macos,go,visualstudiocode

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2021 Oracle and/or its affiliates.
1+
Copyright (c) 2024 Oracle and/or its affiliates.
22

33
The Universal Permissive License (UPL), Version 1.0
44

@@ -32,4 +32,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3232
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3333
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3434
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35-
SOFTWARE.
35+
SOFTWARE.

README.md

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,44 @@
1-
# oke-credential-provider-for-ocir
1+
# Image Credential Provider for OKE
22

3-
[![License: UPL](https://img.shields.io/badge/license-UPL-green)](https://img.shields.io/badge/license-UPL-green) [![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=oracle-devrel_oke-credential-provider-for-ocir)](https://sonarcloud.io/dashboard?id=oracle-devrel_oke-credential-provider-for-ocir)
3+
<b>Image Credential Provider</b> (Provider) for [Container Engine for Kubernetes (OKE)](https://www.oracle.com/cloud/cloud-native/container-engine-kubernetes/) is the implementation of [Kubelet CredentialProvider (v1) APIs](https://kubernetes.io/docs/reference/config-api/kubelet-credentialprovider.v1/) for passwordless pulls from the [Container Registry (OCIR)](https://www.oracle.com/cloud/cloud-native/container-registry/) (OCIR). It's useful since OKE typically [requires](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengpullingimagesfromocir.htm) a stored Secret to pull private OCIR images, referenced with `imagePullSecrets` in a manifest. With the provider in place, Kubelet will pull images using instance principal authentication, giving you a seamless image-pulling experience without hosting static Docker credentials.
44

5-
## THIS IS A NEW, BLANK REPO THAT IS NOT READY FOR USE YET. PLEASE CHECK BACK SOON!
5+
## Table of Contents
6+
- [Prerequisites](#prerequisites)
7+
- [Installation](#installation)
8+
- [Contributing](#contributing)
9+
- [License](#license)
610

7-
## Introduction
8-
MISSING
11+
## Prerequisites
12+
Your OKE Kubelet and API Server versions must be at least v1.26. To check the version, execute `kubectl version`.
913

10-
## Getting Started
11-
MISSING
1214

13-
### Prerequisites
14-
MISSING
15+
## Installation
16+
To install and run the Provider on a worker nodes, follow the steps described [here](/examples/run-on-worker-instance-principal/).
1517

16-
## Notes/Issues
17-
MISSING
18+
It's crucial to (1) [create](#1-create-dynamic-group-for-oke-worker-nodes) a dynamic group to represent worker nodes, (2) [create](#2-create-policy-to-pull-images) a Policy to authorize pulling from OCIR, and (3) [configure](#3-configure-cloud-init-for-oke-node-pool) a cloud-init script to do the heavy lifting.
1819

19-
## URLs
20-
* Nothing at this time
20+
## How the Provider Works
21+
The plugin implementation leverages the Kubelet capability introduced in v1.26. Kubelet uses [CredentialProvider](https://kubernetes.io/docs/reference/config-api/kubelet-credentialprovider.v1/) APIs to fetch authentication credentials against Docker comaptible image registry and caches it on the worker node level. The plugin translates instance principal authentication into the JWT token that is used by Kubelet when pulling images from OCIR at runtime. In that case, you don't need to specify `imagePullSecrets` in a manifest, since Kubelet has JWT token based on instance principal auth locally.
22+
23+
The provider is injected into Kubelet via the extra `kubelet-extra-args`:
24+
- `--image-credential-provider-config` sets the path to the Image Credential Provider for OKE config file.
25+
- `--image-credential-provider-bin-dir` sets the path to the directory where the Image Credential Provider for OKE binary is located.
26+
27+
The cloud-init script act as glue, downloading the provider with the configuration file and passing it to the Kubelet.
28+
29+
The current [cloud-init.sh](examples/run-on-worker-instance-principal/cloud-init.sh) example implementation uses the `wget` utility to download binaries on the worker nodes. Suppose you don't have access to the Internet (through NAT gateway) or your OS does not have a `wget`. In that case, you need to place binaries and configuration in the appropriate folders manually:
30+
- The [provider binary (amd64)](https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/oke-credential-provider-for-ocir-linux-amd64) with the name `oke-credential-provider` must be in the following path: `/usr/local/bin`. Make sure the binary has permission mode to execute. You can enable it by executing `sudo chmod 755 /usr/local/bin/oke-credential-provider`.
31+
- The kubelet configuration file [credential-provider-config.yaml](https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/credential-provider-config.yaml) must be placed in the path `/etc/kubernetes`.
32+
33+
Plugin binaries are avaialble both for OCI [arm64](https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/oke-credential-provider-for-ocir-linux-arm64) and [amd64](https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/oke-credential-provider-for-ocir-linux-amd64) architectures.
2134

2235
## Contributing
23-
This project is open source. Please submit your contributions by forking this repository and submitting a pull request! Oracle appreciates any contributions that are made by the open source community.
36+
37+
If you find a bug or want to suggest an enhancement, please raise the Issue.
2438

2539
## License
26-
Copyright (c) 2022 Oracle and/or its affiliates.
40+
Copyright (c) 2024 Oracle and/or its affiliates.
2741

2842
Licensed under the Universal Permissive License (UPL), Version 1.0.
2943

30-
See [LICENSE](LICENSE) for more details.
31-
32-
ORACLE AND ITS AFFILIATES DO NOT PROVIDE ANY WARRANTY WHATSOEVER, EXPRESS OR IMPLIED, FOR ANY SOFTWARE, MATERIAL OR CONTENT OF ANY KIND CONTAINED OR PRODUCED WITHIN THIS REPOSITORY, AND IN PARTICULAR SPECIFICALLY DISCLAIM ANY AND ALL IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. FURTHERMORE, ORACLE AND ITS AFFILIATES DO NOT REPRESENT THAT ANY CUSTOMARY SECURITY REVIEW HAS BEEN PERFORMED WITH RESPECT TO ANY SOFTWARE, MATERIAL OR CONTENT CONTAINED OR PRODUCED WITHIN THIS REPOSITORY. IN ADDITION, AND WITHOUT LIMITING THE FOREGOING, THIRD PARTIES MAY HAVE POSTED SOFTWARE, MATERIAL OR CONTENT TO THIS REPOSITORY WITHOUT ANY REVIEW. USE AT YOUR OWN RISK.
44+
See [LICENSE](LICENSE) for more details.

cmd/provider.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates.
3+
* Use of this source code is governed by The Universal Permissive License (UPL), Version 1.0. that can be found in the LICENSE file.
4+
*/
5+
6+
package main
7+
8+
import (
9+
"flag"
10+
11+
"github.com/devrocks/credential-provider-oke/internal/helpers"
12+
"github.com/devrocks/credential-provider-oke/internal/provider"
13+
)
14+
15+
func main() {
16+
var configType string
17+
flag.StringVar(&configType, "config", "", "Type the absolute path to yaml file with provider configuration. If it's ommited, program reads from environment variables (REGISTRY_TOKEN_PATH, DEFAULT_USER, REGISTRY_PROTOCOL, OCIR_AUTH_METHOD).")
18+
flag.Parse()
19+
config := helpers.ReadConfig(configType)
20+
provider.GetCredentialProviderResponse(config)
21+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Running the Provider Locally
2+
3+
You can use the following steps to run the provider locally and test the functionality. The script assumes you have OCI CLI installed and configured.
4+
5+
Execute the following command:
6+
```
7+
echo '{
8+
"apiVersion": "credentialprovider.kubelet.k8s.io/v1",
9+
"kind": "CredentialProviderRequest",
10+
"image": "fra.ocir.io/demo_namespace/demo_repo/demo_image"
11+
}' | go run cmd/provider.go -config ./examples/run-locally-yaml/config.yaml
12+
```
13+
14+
If you have OCI CLI installed and configured properly, you should see the output below:
15+
```
16+
{"apiVersion":"credentialprovider.kubelet.k8s.io/v1","kind":"CredentialProviderResponse","cacheKeyType":"Registry","cacheDuration":"0h59m0s","auth":{"fra.ocir.io":{"username":"","password":""}}}
17+
```
18+
19+
That's it!
20+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
registryTokenPath: /20180419/docker/token
2+
defaultUser: BEARER_TOKEN
3+
registryProtocol: https
4+
ocirAuthMethod: USER_PRINCIPAL
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Running the Provider on a Worker Node
2+
3+
To run the Provider on a worker node, follow the steps below. It's crucial to (1) [create](#1-create-dynamic-group-for-oke-worker-nodes) a dynamic group to represent worker nodes, (2) [create](#2-create-policy-to-pull-images) a Policy to authorize pulling from OCIR, and (3) [configure](#3-configure-cloud-init-for-oke-node-pool) a cloud-init script to do the heavy lifting.
4+
5+
## 1. Create Dynamic Group for OKE Worker Nodes
6+
First, you must [create a dynamic group](https://docs.oracle.com/en-us/iaas/Content/Identity/dynamicgroups/To_create_a_dynamic_group.htm) representing worker nodes of a targeted OKE cluster. The example below adds all instances within the compartment to the dynamic group `oke-puller`.
7+
```
8+
All {instance.compartment.id = '<REPLACE_WITH_YOUR_COMPARTMENT_OCID>'}
9+
```
10+
Replace `<REPLACE_WITH_YOUR_COMPARTMENT_OCID>` with the actual compartment OCID where the worker nodes reside. Make sure that targeted worker nodes are a part of the compartment.
11+
12+
Additionally, you might expand the dynamic group expression to defined tags for better precision in selecting worker nodes.
13+
14+
## 2. Create Policy to Pull Images
15+
[Create the policy](https://docs.oracle.com/en-us/iaas/Content/Identity/policymgmt/managingpolicies_topic-To_create_a_policy.htm) to authorize dynamic group `oke-puller` to pull images from OCIR. The example below allows the dynamic group `oke-puller` to pull images from any repository in a selected compartment.
16+
```
17+
Allow dynamic-group <REPLACE_WITH_YOUR_IAM_DOMAIN>/oke-puller to read repos in compartment <REPLACE_WITH_YOUR_COMPARTMENT_NAME>
18+
```
19+
Replace `<REPLACE_WITH_YOUR_IAM_DOMAIN>` with the IAM domain name. Replace `<REPLACE_WITH_YOUR_COMPARTMENT_NAME>` with the compartment name of the repositories with images.
20+
21+
## 3. Configure Cloud-Init for OKE Node Pool
22+
The plugin is activated with the cloud-init executed at the boot time of every worker node. OKE uses cloud-init to set up the compute instances hosting managed nodes. Paste the [following](cloud-init.sh) cloud-init script to every node pool where you want to enable Image Credential Provider for OKE. Node pools must be a part of the dynamic group `oke-puller`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
3+
4+
# download binaries on the worker node
5+
wget https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/oke-credential-provider-for-ocir-linux-amd64 -O /usr/local/bin/credential-provider-oke
6+
wget https://github.com/oracle-devrel/oke-credential-provider-for-ocir/releases/latest/download/credential-provider-config.yaml -P /etc/kubernetes/
7+
8+
# add permission to execute
9+
sudo chmod 755 /usr/local/bin/credential-provider-oke
10+
11+
# configure kubelet with image credential provider
12+
bash /var/run/oke-init.sh --kubelet-extra-args "--image-credential-provider-bin-dir=/usr/local/bin/ --image-credential-provider-config=/etc/kubernetes/credential-provider-config.yaml"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: kubelet.config.k8s.io/v1
2+
kind: CredentialProviderConfig
3+
providers:
4+
- name: credential-provider-oke
5+
apiVersion: credentialprovider.kubelet.k8s.io/v1
6+
matchImages:
7+
- "*.ocir.io"
8+
defaultCacheDuration: 55m
9+
env:
10+
- name: REGISTRY_TOKEN_PATH
11+
value: /20180419/docker/token
12+
- name: DEFAULT_USER
13+
value: BEARER_TOKEN
14+
- name: REGISTRY_PROTOCOL
15+
value: https
16+
- name: OCIR_AUTH_METHOD
17+
value: INSTANCE_PRINCIPAL
18+

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/devrocks/credential-provider-oke
2+
3+
go 1.21.7
4+
5+
require (
6+
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
7+
gopkg.in/yaml.v3 v3.0.1 // indirect
8+
)

0 commit comments

Comments
 (0)