-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
authentication should also life here for simplicity, making jolin rea…
…lly only a higher meta package
- Loading branch information
1 parent
d035b3b
commit 795d13d
Showing
6 changed files
with
122 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
name = "JolinPluto" | ||
uuid = "5b0b4ef8-f4e6-4363-b674-3f031f7b9530" | ||
authors = ["Stephan Sahm <[email protected]> and contributors"] | ||
version = "0.1.92" | ||
version = "0.1.93" | ||
|
||
[deps] | ||
AbstractPlutoDingetjes = "6e696c72-6542-2067-7265-42206c756150" | ||
|
@@ -18,13 +18,14 @@ JWTs = "d850fbd6-035d-5a70-a269-1ca2e636ac6c" | |
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" | ||
|
||
[weakdeps] | ||
AWS = "fbe9abb3-538b-5e4e-ba9e-bc94f4f92ebc" | ||
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" | ||
RCall = "6f49c342-dc21-5d91-9882-a32aef131414" | ||
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab" | ||
|
||
[extensions] | ||
AWSExt = "AWS" | ||
PythonCallExt = "PythonCall" | ||
RCallExt = ["RCall", "CondaPkg"] | ||
RCallExt = "RCall" | ||
|
||
[compat] | ||
julia = "1.7" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
module AWSExt | ||
import Jolin, AWS, JSON3 | ||
using Dates | ||
|
||
function Jolin.authenticate_aws(args...) | ||
mydateformat = Dates.dateformat"yyyymmdd\THHMMSS\Z" | ||
# we define a function in a macro, so that we can use @get_jwt macro (which needs the location) | ||
# as well as use `renew`` argument, which requires a function | ||
function _authenticate_aws(role_arn; audience="", role_session::Union{AbstractString,Nothing}=nothing) | ||
if isnothing(role_session) | ||
role_session = AWS._role_session_name( | ||
"jolincloud-role-", | ||
basename(role_arn), | ||
"-" * Dates.format(Dates.now(Dates.UTC), mydateformat), | ||
) | ||
end | ||
# we need to be cautious that @get_jwt is called with the same __source__ | ||
web_identity = Jolin.jolin_token(audience) | ||
|
||
response = AWS.AWSServices.sts( | ||
"AssumeRoleWithWebIdentity", | ||
Dict( | ||
"RoleArn" => role_arn, | ||
"RoleSessionName" => role_session, # Required by AssumeRoleWithWebIdentity | ||
"WebIdentityToken" => web_identity, | ||
); | ||
aws_config=AWS.AWSConfig(; creds=nothing), | ||
feature_set=AWS.FeatureSet(; use_response_type=true), | ||
) | ||
dict = JSON3.read(response) | ||
role_creds = dict["AssumeRoleWithWebIdentityResult"]["Credentials"] | ||
assumed_role_user = dict["AssumeRoleWithWebIdentityResult"]["AssumedRoleUser"] | ||
|
||
return AWS.global_aws_config(creds=AWS.AWSCredentials( | ||
role_creds["AccessKeyId"], | ||
role_creds["SecretAccessKey"], | ||
role_creds["SessionToken"], | ||
assumed_role_user["Arn"]; | ||
expiry=Dates.DateTime(rstrip(role_creds["Expiration"], 'Z')), | ||
renew=() -> _authenticate_aws(role_arn; audience, role_session).credentials, | ||
)) | ||
end | ||
_authenticate_aws(args...) | ||
end | ||
|
||
end # module |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import HTTP | ||
import JSON3 | ||
using JWTs: JWT | ||
using Git: git | ||
|
||
""" | ||
authenticate_token() | ||
authenticate_token("exampleaudience") | ||
Creates a JSON Web Token which can be used for authentication at common cloud providers. | ||
On cloud.jolin.io the token will be issued and signed by cloud.jolin.io, | ||
on Github Actions (used for automated tests), a respective github token is returned. | ||
""" | ||
function authenticate_token(audience="") | ||
# Jolin Cloud | ||
if parse(Bool, get(ENV, "JOLIN_CLOUD", "false")) | ||
serviceaccount_token = readchomp("/var/run/secrets/kubernetes.io/serviceaccount/token") | ||
path = Main.PlutoRunner.notebook_path[] | ||
project_dir = readchomp(`$(git()) -C $(dirname(path)) rev-parse --show-toplevel`) | ||
@assert startswith(path, project_dir) "invalid workflow location" | ||
workflowpath = path[length(project_dir)+2:end] | ||
|
||
response = HTTP.get("http://jolin-workspace-server-jwts.jolin-workspace-server/request_jwt", | ||
query=["serviceaccount_token" => serviceaccount_token, | ||
"workflowpath" => workflowpath, | ||
"audience" => audience]) | ||
return JSON3.read(response.body).token | ||
|
||
# Github Actions | ||
elseif (parse(Bool, get(ENV, "CI", "false")) | ||
&& haskey(ENV, "ACTIONS_ID_TOKEN_REQUEST_TOKEN") | ||
&& haskey(ENV, "ACTIONS_ID_TOKEN_REQUEST_URL")) | ||
response = HTTP.get(ENV["ACTIONS_ID_TOKEN_REQUEST_URL"], | ||
query=["audience" => audience], | ||
headers=["Authorization" => "bearer " * ENV["ACTIONS_ID_TOKEN_REQUEST_TOKEN"]]) | ||
# the token is in subfield value https://blog.alexellis.io/deploy-without-credentials-using-oidc-and-github-actions/ | ||
return JSON3.read(response.body).value | ||
|
||
# using a specific environment variable to set the token from the outside for local development purposes | ||
elseif haskey(ENV, "JOLIN_JWT_FALLBACK") | ||
return ENV["JOLIN_JWT_FALLBACK"] | ||
|
||
# Fallback with Dummy Value | ||
else | ||
payload = Dict( | ||
"iss" => "http://www.example.com/", | ||
"sub" => "/env/YOUR_ENV/github.com/YOUR_ORGANIZATION/YOUR_REPO/PATH/TO/WORKFLOW", | ||
"aud" => audience, | ||
"exp" => 1536080651, | ||
"iat" => 1535994251, | ||
) | ||
# for details see https://github.com/tanmaykm/JWTs.jl/issues/22 | ||
jwt = JWT(; payload) | ||
return ".$jwt." | ||
end | ||
end | ||
|
||
|
||
""" | ||
authenticate_aws(role_arn; audience="") | ||
Assume role via web identity. How to define such a role can be found here | ||
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html#cli-configure-role-oidc | ||
""" | ||
function authenticate_aws end | ||
|
||
# TODO add Azure, Google Cloud and HashiCorp |