Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support function authentication with OpenFaaS IAM #996

Merged
merged 6 commits into from
Jun 19, 2024

Conversation

welteki
Copy link
Member

@welteki welteki commented May 24, 2024

Description

Support invoking functions that have the OpenFaaS IAM based built in function authentication enabled.

The CLI now uses the client.InvokeFunction method from the OpenFaaS go-sdk to invoke functions. Support for IAM authentication is part of the go-sdk. The SDK will handle exchanging the OpenFaaS API access token for a function access token that is only valid for the requested function.

The invoke command automatically tries to detect if a function requires authentication. This is done by invoking the function without an Authorization header. If the function responds with a 401 (Unauthorized) response status the CLI looks at the realm directive in the WWW-Authenticate header to check if the function requires authentication. The request is retried this time with authentication.

This change also adds a new optional flag, --auth to the invoke command. If the flag is set the CLI will skip the check to detect if authentication is required and immediately invoke the function with a function access token.

When running function with the local-run command, the OPENFAAS_NAME and OPENFAAS_NAMESPACE env
variables are set together with jwt_local_auth to support built-in function authentication.

Motivation and Context

  • I have raised an issue to propose this change (required)

Support IAM authentication for functions.

How Has This Been Tested?

  • Unit test were added to cover changes.

  • Verified header, query parameters, and the content type set through flags are correctly used in the request.

  • Verified it is possible to sign the request.

  • Verified functions without authentication can be invoked.

    export FAAS_DEBUG=true
    echo | ./faas-cli invoke env
    
    POST https://gw.example.com/function/env.openfaas-fn
    Content-Type: [text/plain]
    
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=env-86d79fd685-7ngmn
    OPENFAAS_NAME=env
    fprocess=env
    HOME=/home/app
    Http_Content_Type=text/plain
    Http_X_Forwarded_Uri=/function/env.openfaas-fn
    Http_X_Start_Time=1716564494196297298
    Http_X_Call_Id=054ccda4-73b4-4054-9c50-d2dc9897034c
    Http_User_Agent=Go-http-client/1.1
    Http_Method=POST
    ...
  • Verified functions that require authentication can be invoked.

    export FAAS_DEBUG=true
    echo | ./faas-cli invoke alpine
    
    POST https://gw.example.com/function/alpine.openfaas-fn
    Content-Type: [text/plain]
    
    POST https://gw.example.com/function/alpine.openfaas-fn
    Content-Type: [text/plain]
    Authorization: Bearer REDACTED
    
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=alpine-5b86546786-h667k
    jwt_auth=true
    OPENFAAS_NAME=alpine
    fprocess=env
    HOME=/home/app
    Http_Accept_Encoding=gzip
    Http_Authorization=Bearer REDACTED
    Http_Content_Type=text/plain
    Http_X_Start_Time=1716564766604284251
    Http_User_Agent=Go-http-client/1.1
    Http_X_Forwarded_Uri=/function/alpine.openfaas-fn
    Http_X_Call_Id=5637ac7c-bd72-4a57-94db-f7090d9a1c68
    ...
  • Verified the bearer is included in the first call when the --auth flag is set.

    export FAAS_DEBUG=true
    echo | ./faas-cli invoke alpine --auth
    
    POST https://gw.example.com/function/alpine.openfaas-fn
    Content-Type: [text/plain]
    Authorization: Bearer REDACTED
    
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=alpine-5b86546786-h667k
    jwt_auth=true
    OPENFAAS_NAME=alpine
    fprocess=env
    HOME=/home/app
    Http_User_Agent=Go-http-client/1.1
    Http_Accept_Encoding=gzip
    Http_Content_Type=text/plain
    Http_X_Call_Id=406c0a77-8b37-401e-a901-b68a4c7d32e4
    Http_Authorization=Bearer REDACTED
    Http_X_Forwarded_Uri=/function/alpine.openfaas-fn
    Http_X_Start_Time=1716565000220711406
    Http_Method=POST
    Http_Path=/
    ...
  • Verified functions that require authentication can be invoked asynchronously.

    echo | ./faas-cli invoke alpine --auth --async
    
    POST https://gw.example.com/async-function/alpine.openfaas-fn
    Content-Type: [text/plain]
    Authorization: Bearer REDACTED
    
    Function submitted asynchronously.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I've read the CONTRIBUTION guide
  • I have signed-off my commits with git commit -s
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@alexellis
Copy link
Member

In this example, I see the --auth flag mentioned, but it's not given in the example?

image

@welteki
Copy link
Member Author

welteki commented May 29, 2024

In this example, I see the --auth flag mentioned, but it's not given in the example?

This is a mistake, I updated the example and I can confirm the --auth flag is working.

welteki added 3 commits June 10, 2024 10:45
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
Don't exit the program when looking up the auth config fails but print a
warning instead.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
@welteki welteki marked this pull request as ready for review June 14, 2024 14:08
@@ -23,14 +23,14 @@ func Test_invoke(t *testing.T) {
s := test.MockHttpServer(t, []test.Request{
{
Method: http.MethodPost,
Uri: "/function/" + funcName,
Uri: "/function/" + funcName + ".openfaas-fn",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the namespace needed now?

It should still be possible to invoke without a namespace suffix, so I'm unsure why this change was made.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The go-sdk which, is now used to invoke functions, always needs a namespace to be specified. This is required for getting access tokens for functions if the function is authenticated (the full reference to a function, including the namespace, is required to request an access token)

This is why a function will always be invoked in the default namespace openfaas-fn if no namespace is provided explicitly.

Copy link
Member

@alexellis alexellis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please could you respond to the comments?

welteki added 3 commits June 17, 2024 13:18
Ensure the default sdk client reads the provider url from the stack file
if the '--yaml/-f' flag is used.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
Try to lookup the function namespace in the stack file before falling
back to the default namespace.

This is the default behaviour for all other commands and should be
implemeted for invoke as well.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
Set env variables that are normally injects by the provider like,
'OPENFAAS_NAME' and 'OPENFAAS_NAMESPACE' when running function with
local-run.

This change makes it possible to use built-in function authentication
with local-run. The 'jwt_auth_local' env variable is to true by default
to help with this.

Signed-off-by: Han Verstraete (OpenFaaS Ltd) <[email protected]>
Copy link
Member

@alexellis alexellis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved

@alexellis alexellis merged commit 3fd37fb into openfaas:master Jun 19, 2024
1 check passed
@welteki welteki deleted the function-auth branch August 8, 2024 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants