1
- PACKIT_URL <- " https://packit.dide.ic.ac.uk/reside"
2
-
3
- get_packit_audience <- function (base_url ) {
4
- response <- httr2 :: request(base_url ) | >
1
+ get_packit_audience <- function (url ) {
2
+ response <- httr2 :: request(url ) | >
5
3
httr2 :: req_url_path_append(" packit/api/auth/login/service/audience" ) | >
6
4
httr2 :: req_perform() | >
7
5
httr2 :: resp_body_json()
8
6
response $ audience
9
7
}
10
8
9
+ check_audience <- function (url ) {
10
+ # The server will match its configured audience against the one found in the
11
+ # token exactly. A mismatch could occur if, for example, the user provided a
12
+ # non-canonical URL that routes to the same place but isn't strictly equal
13
+ # (eg. using `https://hostname:443` instead of just `https://hostname`).
14
+ #
15
+ # It is tempting to just use the audience provided by the server instead of
16
+ # PACKIT_URL and not have to worry about it ever failing to match. If we did
17
+ # that though, a malicious server could present an arbitrary audience and use
18
+ # the token we give it to login to a completely different service on behalf on
19
+ # this action, and we do not want to allow that.
20
+ #
21
+ # This warning provides an easy diagnostic and resolution path for the benign
22
+ # case of a non-canonical URL, while avoiding the aforementioned pitfall.
23
+ expected_audience <- get_packit_audience(url )
24
+ if (expected_audience != url ) {
25
+ cli :: cli_warn(
26
+ paste(" The Packit URL is {.url {url}}, but the server is expecting" ,
27
+ " the audience to be {.url {expected_audience}}. Authentication is" ,
28
+ " likely to fail." ))
29
+ }
30
+ }
31
+
11
32
get_oidc_token <- function (audience ) {
12
33
url <- Sys.getenv(" ACTIONS_ID_TOKEN_REQUEST_URL" , NA )
13
34
token <- Sys.getenv(" ACTIONS_ID_TOKEN_REQUEST_TOKEN" , NA )
@@ -26,19 +47,28 @@ get_oidc_token <- function(audience) {
26
47
response $ value
27
48
}
28
49
29
- get_packit_token <- function (base_url , token ) {
30
- response <- httr2 :: request(base_url ) | >
50
+ get_packit_token_service <- function (url , token ) {
51
+ response <- httr2 :: request(url ) | >
31
52
httr2 :: req_url_path_append(" packit/api/auth/login/service" ) | >
32
53
httr2 :: req_body_json(list (token = token )) | >
33
54
httr2 :: req_perform() | >
34
55
httr2 :: resp_body_json()
35
56
response $ token
36
57
}
37
58
38
- task_run <- function (branch , hash , name ) {
39
- req <- httr2 :: request(PACKIT_URL ) | >
59
+ get_packit_token_api <- function (url , token ) {
60
+ response <- httr2 :: request(url ) | >
61
+ httr2 :: req_url_path_append(" packit/api/auth/login/api" ) | >
62
+ httr2 :: req_body_json(list (token = token )) | >
63
+ httr2 :: req_perform() | >
64
+ httr2 :: resp_body_json()
65
+ response $ token
66
+ }
67
+
68
+ task_run <- function (url , token , branch , hash , name ) {
69
+ req <- httr2 :: request(url ) | >
40
70
httr2 :: req_url_path_append(" packit/api/runner/run" ) | >
41
- httr2 :: req_auth_bearer_token(packit_token ) | >
71
+ httr2 :: req_auth_bearer_token(token ) | >
42
72
httr2 :: req_body_json(list (name = name , branch = branch , hash = hash ))
43
73
44
74
task <- httr2 :: req_perform(req ) | >
@@ -47,59 +77,62 @@ task_run <- function(branch, hash, name) {
47
77
task $ taskId
48
78
}
49
79
50
- task_status <- function (task_id , include_logs = FALSE ) {
51
- req <- httr2 :: request(PACKIT_URL ) | >
52
- httr2 :: req_auth_bearer_token(packit_token ) | >
80
+ task_status <- function (url , token , task_id , include_logs = FALSE ) {
81
+ req <- httr2 :: request(url ) | >
82
+ httr2 :: req_auth_bearer_token(token ) | >
53
83
httr2 :: req_url_path_append(" packit/api/runner/status" , task_id ) | >
54
84
httr2 :: req_url_query(includeLogs = include_logs )
55
85
56
86
httr2 :: req_perform(req ) | >
57
87
httr2 :: resp_body_json()
58
88
}
59
89
60
- task_wait <- function (task_id ) {
90
+ task_wait <- function (url , token , task_id ) {
61
91
while (TRUE ) {
62
- status <- task_status(task_id )
92
+ status <- task_status(url , token , task_id )
63
93
if (status $ status != " RUNNING" ) {
64
94
return (invisible (status ))
65
95
}
66
96
Sys.sleep(1 )
67
97
}
68
98
}
69
99
70
- # The server will match its configured audience against the one found in the
71
- # token exactly. A mismatch could occur if, for example, the user provided a
72
- # non-canonical URL that routes to the same place but isn't strictly equal
73
- # (eg. using `https://hostname:443` instead of just `https://hostname`).
74
- #
75
- # It is tempting to just use the audience provided by the server instead of
76
- # PACKIT_URL and not have to worry about it ever failing to match. If we did
77
- # that though, a malicious server could present an arbitrary audience and use
78
- # the token we give it to login to a completely different service on behalf on
79
- # this action, and we do not want to allow that.
80
- #
81
- # This warning provides an easy diagnostic and resolution path for the benign
82
- # case of a non-canonical URL, while avoiding the aforementioned pitfall.
83
- expected_audience <- get_packit_audience(PACKIT_URL )
84
- if (expected_audience != PACKIT_URL ) {
85
- cli :: cli_warn(
86
- paste(" The Packit URL is {.url {PACKIT_URL}}, but the server is expecting" ,
87
- " the audience to be {.url {expected_audience}}. Authentication is" ,
88
- " likely to fail." ))
100
+ authenticate <- function (url ) {
101
+ packit_token <- Sys.getenv(" PACKIT_TOKEN" , NA )
102
+ if (! is.na(packit_token )) {
103
+ return (packit_token )
104
+ }
105
+
106
+ github_token <- Sys.getenv(" GITHUB_TOKEN" , NA )
107
+ if (! is.na(github_token )) {
108
+ return (get_packit_token_api(url , github_token ))
109
+ }
110
+
111
+ check_audience(url )
112
+ github_token <- get_oidc_token(url )
113
+ get_packit_token_service(url , github_token )
89
114
}
90
115
91
- github_token <- get_oidc_token(PACKIT_URL )
92
- packit_token <- get_packit_token(PACKIT_URL , github_token )
116
+ main <- function (args = commandArgs(trailingOnly = TRUE )) {
117
+ url <- args [[1 ]]
118
+ input <- args [[2 ]]
119
+
120
+ ref_name <- Sys.getenv(" GITHUB_REF_NAME" , " main" )
121
+ sha <- Sys.getenv(" GITHUB_SHA" , " HEAD" )
93
122
94
- ref_name <- Sys.getenv(" GITHUB_REF_NAME" , " main" )
95
- sha <- Sys.getenv(" GITHUB_SHA" , " HEAD" )
96
- name <- " incoming_data"
123
+ token <- authenticate(url )
124
+ data <- yaml :: read_yaml(file = input )
97
125
98
- task_id <- task_run(ref_name , sha , name )
99
- task_wait(task_id )
100
- status <- task_status(task_id )
101
- writeLines(unlist(status $ logs ))
126
+ for (entry in data ) {
127
+ task_id <- task_run(url , token , ref_name , sha , entry $ name )
128
+ task_wait(url , token , task_id )
129
+ status <- task_status(url , token , task_id , include_logs = TRUE )
130
+ writeLines(unlist(status $ logs ))
102
131
103
- if (status $ status != " COMPLETE" ) {
104
- cli :: cli_abort(" Task failed" )
132
+ if (status $ status != " COMPLETE" ) {
133
+ cli :: cli_abort(" Task failed" )
134
+ }
135
+ }
105
136
}
137
+
138
+ main()
0 commit comments