Skip to content
This repository was archived by the owner on Jul 6, 2023. It is now read-only.

Commit 2065f67

Browse files
committed
Implement VK with token refresh
1 parent ffbfc7a commit 2065f67

File tree

10 files changed

+191
-17
lines changed

10 files changed

+191
-17
lines changed

.github/workflows/build_images.yaml

+32
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,38 @@ jobs:
3737
file: ./Dockerfile.vk
3838
platforms: linux/amd64, linux/arm64
3939

40+
virtual-kubelet-refrest-token:
41+
runs-on: ubuntu-latest
42+
#env:
43+
# DOCKER_TARGET_PLATFORM: linux/arm64
44+
steps:
45+
- name: Checkout
46+
uses: actions/checkout@v2
47+
- name: Set env
48+
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
49+
- name: Set up QEMU
50+
uses: docker/setup-qemu-action@v1
51+
- name: Set up Docker Buildx
52+
uses: docker/setup-buildx-action@v1
53+
- name: Login to GitHub Container Registry
54+
uses: docker/login-action@v1
55+
with:
56+
registry: ghcr.io
57+
username: ${{ github.repository_owner }}
58+
password: ${{ secrets.GITHUB_TOKEN }}
59+
- name: Get Repo Owner
60+
id: get_repo_owner
61+
run: echo ::set-output name=repo_owner::$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')
62+
- name: Build container base image
63+
uses: docker/build-push-action@v2
64+
with:
65+
context: ./
66+
outputs: "type=registry,push=true"
67+
tags: |
68+
ghcr.io/${{ steps.get_repo_owner.outputs.repo_owner }}/virtual-kubelet-inttw-refresh:${{ env.RELEASE_VERSION }}
69+
file: ./Dockerfile.refresh-token
70+
platforms: linux/amd64, linux/arm64
71+
4072
interlink:
4173
runs-on: ubuntu-latest
4274
#env:

Dockerfile.refresh-token

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM python:3.10
2+
3+
RUN pip3 install requests
4+
5+
COPY ./scripts/refresh.py /opt/refresh.py
6+
7+
ENTRYPOINT ["python3", "/opt/refresh.py"]

docs/itwinctl.sh

+10-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#export INTERLINKCONFIGPATH="$PWD/kustomizations/InterLinkConfig.yaml"
44

5-
VERSION="${VERSION:-0.0.4}"
5+
VERSION="${VERSION:-0.0.5}"
66

77
OS=$(uname -s)
88

@@ -30,13 +30,14 @@ AUTHORIZED_GROUPS="${AUTHORIZED_GROUPS:-intw}"
3030
AUTHORIZED_AUD="${AUTHORIZED_AUD:-intertw-vk}"
3131
API_HTTP_PORT="${API_HTTP_PORT:-8080}"
3232
API_HTTPS_PORT="${API_HTTPS_PORT:-443}"
33-
INTERLINKPORT="${INTERLINKPORT:-3000}"
34-
INTERLINKURL="${INTERLINKURL:-http://0.0.0.0}"
35-
INTERLINKPORT="${INTERLINKPORT:-3000}"
36-
INTERLINKURL="${INTERLINKURL:-http://0.0.0.0}"
37-
INTERLINKCONFIGPATH="${INTERLINKCONFIGPATH:-$HOME/.config/interlink/InterLinkConfig.yaml}"
33+
export INTERLINKPORT="${INTERLINKPORT:-3000}"
34+
export INTERLINKURL="${INTERLINKURL:-http://0.0.0.0}"
35+
export INTERLINKPORT="${INTERLINKPORT:-3000}"
36+
export INTERLINKURL="${INTERLINKURL:-http://0.0.0.0}"
37+
export INTERLINKCONFIGPATH="${INTERLINKCONFIGPATH:-$HOME/.config/interlink/InterLinkConfig.yaml}"
38+
export SBATCHPATH="${SBATCHPATH:-/usr/bin/sbatch}"
39+
export SCANCELPATH="${SCANCELPATH:-/usr/bin/scancel}"
3840

39-
export INTERLINKCONFIGPATH=$INTERLINKCONFIGPATH
4041

4142
install () {
4243
mkdir -p $HOME/.local/interlink/logs || exit 1
@@ -119,4 +120,6 @@ case "$1" in
119120
stop
120121
start
121122
;;
123+
uninstall)
124+
rm -r $HOME/.local/interlink
122125
esac

kustomizations/InterLinkConfig.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
VKTokenFile: "/opt/interlink/token"
12
InterlinkURL: "http://localhost"
23
SidecarURL: "http://localhost"
34
InterlinkPort: "3000"
45
SidecarService: "slurm" #docker, slurm
56
SbatchPath: "/usr/bin/sbatch"
6-
ScancelPath: "/usr/bin/sbatch"
7+
ScancelPath: "/usr/bin/scancel"
78
CommandPrefix: ""
89
Tsocks: false
910
TsocksPath: "$WORK/tsocks-1.8beta5+ds1/libtsocks.so"

kustomizations/deployment.yaml

+38-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ spec:
4343
fieldPath: status.podIP
4444
- name: INTERLINKCONFIGPATH
4545
value: "/etc/interlink/InterLinkConfig.yaml"
46+
- name: VKTOKENFILE
47+
value: "/opt/interlink/token"
4648
- name: VK_CONFIG_PATH
4749
value: "/etc/interlink/knoc-cfg.json"
4850
volumeMounts:
@@ -52,6 +54,40 @@ spec:
5254
- name: config-json
5355
mountPath: /etc/interlink/knoc-cfg.json
5456
subPath: knoc-cfg.json
57+
- name: token
58+
mountPath: /opt/interlink
59+
resources:
60+
limits:
61+
cpu: 2000m
62+
memory: 2Gi
63+
requests:
64+
cpu: 2000m
65+
memory: 2Gi
66+
- name: refresh-token
67+
image: docker.io/surax98/vk:latest
68+
imagePullPolicy: Always
69+
env:
70+
- name: IAM_SERVER
71+
value: "https://dodas-iam.cloud.cnaf.infn.it/"
72+
# TODO load env IAM client from secret
73+
- name: IAM_CLIENT_ID
74+
value: "DUMMY"
75+
- name: IAM_CLIENT_SECRET
76+
value: "DUMMY"
77+
- name: IAM_VK_AUD
78+
value: intertw-vk
79+
- name: TOKEN_PATH
80+
value: /opt/interlink/token
81+
resources:
82+
limits:
83+
cpu: 2000m
84+
memory: 2Gi
85+
requests:
86+
cpu: 2000m
87+
memory: 2Gi
88+
volumeMounts:
89+
- name: token
90+
mountPath: /opt/interlink
5591
serviceAccountName: knoc
5692
volumes:
5793
- name: config
@@ -62,5 +98,6 @@ spec:
6298
configMap:
6399
# Provide the name of the ConfigMap you want to mount.
64100
name: test-vk-config
65-
101+
- name: token
102+
emptyDir: {}
66103

pkg/common/func.go

+13
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,19 @@ func NewInterLinkConfig() {
102102
InterLinkConfigInst.Tsockspath = path
103103
}
104104

105+
if os.Getenv("VKTOKENFILE") != "" {
106+
path := os.Getenv("VKTOKENFILE")
107+
if _, err := os.Stat(path); err != nil {
108+
log.Println("File " + path + " doesn't exist. You can set a custom path by exporting VKTOKENFILE. Exiting...")
109+
os.Exit(-1)
110+
}
111+
112+
InterLinkConfigInst.VKTokenFile = path
113+
} else {
114+
path = "/tmp/token"
115+
InterLinkConfigInst.VKTokenFile = path
116+
}
117+
105118
InterLinkConfigInst.set = true
106119
}
107120
}

pkg/common/types.go

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Request struct {
2929
}
3030

3131
type InterLinkConfig struct {
32+
VKTokenFile string `yaml:"VKTokenFile"`
3233
Interlinkurl string `yaml:"InterlinkURL"`
3334
Sidecarurl string `yaml:"SidecarURL"`
3435
Sbatchpath string `yaml:"SbatchPath"`

pkg/virtualkubelet/execute.go

+19-7
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import (
44
"bytes"
55
"context"
66
"encoding/json"
7+
"fmt"
78
"io/ioutil"
89
"net/http"
10+
"os"
911
"strings"
1012

1113
common "github.com/CARV-ICS-FORTH/knoc/common"
@@ -18,7 +20,7 @@ import (
1820

1921
var NoReq uint8
2022

21-
func createRequest(pod commonIL.Request) []byte {
23+
func createRequest(pod commonIL.Request, token string) []byte {
2224
var returnValue, _ = json.Marshal(commonIL.PodStatus{PodStatus: commonIL.UNKNOWN})
2325

2426
bodyBytes, err := json.Marshal(pod)
@@ -29,6 +31,7 @@ func createRequest(pod commonIL.Request) []byte {
2931
log.L.Error(err)
3032
}
3133

34+
req.Header.Add("Authorization", "Bearer "+token)
3235
resp, err := http.DefaultClient.Do(req)
3336
if err != nil {
3437
log.L.Error(err)
@@ -41,7 +44,7 @@ func createRequest(pod commonIL.Request) []byte {
4144
return returnValue
4245
}
4346

44-
func deleteRequest(pod commonIL.Request) []byte {
47+
func deleteRequest(pod commonIL.Request, token string) []byte {
4548
var returnValue, _ = json.Marshal(commonIL.PodStatus{PodStatus: commonIL.UNKNOWN})
4649

4750
bodyBytes, err := json.Marshal(pod)
@@ -51,6 +54,7 @@ func deleteRequest(pod commonIL.Request) []byte {
5154
log.L.Error(err)
5255
}
5356

57+
req.Header.Add("Authorization", "Bearer "+token)
5458
resp, err := http.DefaultClient.Do(req)
5559
if err != nil {
5660
log.L.Error(err)
@@ -63,7 +67,7 @@ func deleteRequest(pod commonIL.Request) []byte {
6367
return returnValue
6468
}
6569

66-
func statusRequest(podsList commonIL.Request) []byte {
70+
func statusRequest(podsList commonIL.Request, token string) []byte {
6771
var returnValue []byte
6872
var response []commonIL.StatusResponse
6973

@@ -76,6 +80,8 @@ func statusRequest(podsList commonIL.Request) []byte {
7680

7781
log.L.Println(string(bodyBytes))
7882

83+
req.Header.Add("Authorization", "Bearer "+token)
84+
7985
resp, err := http.DefaultClient.Do(req)
8086
if err != nil {
8187
log.L.Error(err)
@@ -91,26 +97,32 @@ func RemoteExecution(p *VirtualKubeletProvider, ctx context.Context, mode int8,
9197
var req commonIL.Request
9298
req.Pods = map[string]*v1.Pod{pod.Name: pod}
9399

100+
b, err := os.ReadFile(commonIL.InterLinkConfigInst.VKTokenFile) // just pass the file name
101+
if err != nil {
102+
fmt.Print(err)
103+
}
104+
token := string(b)
105+
94106
switch mode {
95107
case common.CREATE:
96108
//v1.Pod used only for secrets and volumes management; TO BE IMPLEMENTED
97-
returnVal := createRequest(req)
109+
returnVal := createRequest(req, token)
98110
log.L.Println(string(returnVal))
99111
break
100112

101113
case common.DELETE:
102114
if NoReq > 0 {
103115
NoReq--
104116
} else {
105-
returnVal := deleteRequest(req)
117+
returnVal := deleteRequest(req, token)
106118
log.L.Println(string(returnVal))
107119
}
108120
break
109121
}
110122
return nil
111123
}
112124

113-
func checkPodsStatus(p *VirtualKubeletProvider, ctx context.Context) {
125+
func checkPodsStatus(p *VirtualKubeletProvider, ctx context.Context, token string) {
114126
if len(p.pods) == 0 {
115127
return
116128
}
@@ -119,7 +131,7 @@ func checkPodsStatus(p *VirtualKubeletProvider, ctx context.Context) {
119131
var PodsList commonIL.Request
120132
PodsList.Pods = p.pods
121133

122-
returnVal = statusRequest(PodsList)
134+
returnVal = statusRequest(PodsList, token)
123135
json.Unmarshal(returnVal, &ret)
124136

125137
for podIndex, podStatus := range ret.PodStatus {

pkg/virtualkubelet/virtualkubelet.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"io"
88
"io/ioutil"
99
"math/rand"
10+
"os"
1011
"time"
1112

1213
"github.com/CARV-ICS-FORTH/knoc"
@@ -573,6 +574,12 @@ func (p *VirtualKubeletProvider) statusLoop(ctx context.Context) {
573574
<-t.C
574575
}
575576

577+
b, err := os.ReadFile(commonIL.InterLinkConfigInst.VKTokenFile) // just pass the file name
578+
if err != nil {
579+
fmt.Print(err)
580+
}
581+
token := string(b)
582+
576583
for {
577584
t.Reset(5 * time.Second)
578585
select {
@@ -581,7 +588,12 @@ func (p *VirtualKubeletProvider) statusLoop(ctx context.Context) {
581588
case <-t.C:
582589
}
583590

584-
checkPodsStatus(p, ctx)
591+
b, err = os.ReadFile(commonIL.InterLinkConfigInst.VKTokenFile) // just pass the file name
592+
if err != nil {
593+
fmt.Print(err)
594+
}
595+
token = string(b)
596+
checkPodsStatus(p, ctx, token)
585597
}
586598
}
587599

scripts/refresh.py

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#! /bin/env python3
2+
"""
3+
Functions and scripts to sync OIDC identities on user accounts
4+
"""
5+
6+
import os
7+
import json
8+
import time
9+
import logging
10+
import requests
11+
12+
if __name__ == '__main__':
13+
"""
14+
sync OIDC identities on user accounts
15+
"""
16+
try:
17+
iam_server = os.environ.get(
18+
"IAM_SERVER", "https://cms-auth.web.cern.ch/")
19+
iam_client_id = os.environ.get("IAM_CLIENT_ID")
20+
iam_client_secret = os.environ.get("IAM_CLIENT_SECRET")
21+
audience = os.environ.get("IAM_VK_AUD")
22+
output_file = os.environ.get("TOKEN_PATH", "/opt/interlink/token")
23+
except Exception as ex:
24+
print(ex)
25+
exit(1)
26+
27+
token = None
28+
29+
while True:
30+
try:
31+
request_data = {
32+
"client_id": iam_client_id,
33+
"client_secret": iam_client_secret,
34+
"grant_type": "client_credentials",
35+
"username": "not_needed",
36+
"password": "not_needed",
37+
"scope": "openid profile email iam",
38+
"aud": audience
39+
}
40+
r = requests.post(iam_server+"token", data=request_data)
41+
response = json.loads(r.text)
42+
43+
#print(iam_client_id, iam_client_secret, response)
44+
token = response['access_token']
45+
46+
logging.info("Token retrieved")
47+
48+
with open(output_file, "w") as text_file:
49+
text_file.write(token)
50+
51+
logging.info(f"Token written in {output_file}")
52+
53+
except Exception as e:
54+
logging.warn("ERROR oidc get token: {}".format(e))
55+
56+
time.sleep(600)

0 commit comments

Comments
 (0)