From 1e6647bfa26824b8acb458c25918fa2c99836374 Mon Sep 17 00:00:00 2001 From: Idan Novogroder <43949240+idanovo@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:12:55 +0300 Subject: [PATCH] Add AWS remote auth login (#7578) --- api/authentication.yml | 58 ++++ api/swagger.yml | 54 ++- clients/java-legacy/.openapi-generator/FILES | 3 + clients/java-legacy/README.md | 4 + clients/java-legacy/api/openapi.yaml | 73 +++- clients/java-legacy/docs/AuthApi.md | 67 ++++ clients/java-legacy/docs/ExperimentalApi.md | 68 ++++ clients/java-legacy/docs/ExternalApi.md | 67 ++++ .../docs/ExternalLoginInformation.md | 14 + clients/java-legacy/docs/StsAuthRequest.md | 2 +- .../java/io/lakefs/clients/api/AuthApi.java | 131 ++++++++ .../lakefs/clients/api/ExperimentalApi.java | 135 ++++++++ .../io/lakefs/clients/api/ExternalApi.java | 132 ++++++++ .../api/model/ExternalLoginInformation.java | 127 +++++++ .../clients/api/model/StsAuthRequest.java | 4 +- .../io/lakefs/clients/api/AuthApiTest.java | 16 + .../clients/api/ExperimentalApiTest.java | 16 + .../lakefs/clients/api/ExternalApiTest.java | 17 + .../model/ExternalLoginInformationTest.java | 59 ++++ clients/java/README.md | 4 + clients/java/api/openapi.yaml | 73 +++- clients/java/docs/AuthApi.md | 69 ++++ clients/java/docs/ExperimentalApi.md | 70 ++++ clients/java/docs/ExternalApi.md | 69 ++++ clients/java/docs/ExternalLoginInformation.md | 14 + clients/java/docs/StsAuthRequest.md | 2 +- .../java/io/lakefs/clients/sdk/AuthApi.java | 186 ++++++++++ .../lakefs/clients/sdk/ExperimentalApi.java | 191 +++++++++++ .../io/lakefs/clients/sdk/ExternalApi.java | 187 ++++++++++ .../main/java/io/lakefs/clients/sdk/JSON.java | 1 + .../sdk/model/ExternalLoginInformation.java | 318 ++++++++++++++++++ .../clients/sdk/model/StsAuthRequest.java | 2 +- .../io/lakefs/clients/sdk/AuthApiTest.java | 15 + .../clients/sdk/ExperimentalApiTest.java | 15 + .../lakefs/clients/sdk/ExternalApiTest.java | 16 + .../model/ExternalLoginInformationTest.java | 56 +++ .../python-legacy/.openapi-generator/FILES | 3 + clients/python-legacy/README.md | 4 + clients/python-legacy/docs/AuthApi.md | 78 +++++ clients/python-legacy/docs/ExperimentalApi.md | 79 +++++ clients/python-legacy/docs/ExternalApi.md | 78 +++++ .../docs/ExternalLoginInformation.md | 13 + clients/python-legacy/docs/StsAuthRequest.md | 2 +- .../lakefs_client/api/auth_api.py | 110 ++++++ .../lakefs_client/api/experimental_api.py | 110 ++++++ .../lakefs_client/api/external_api.py | 111 ++++++ .../model/external_login_information.py | 266 +++++++++++++++ .../lakefs_client/model/sts_auth_request.py | 4 +- .../lakefs_client/models/__init__.py | 1 + clients/python-legacy/test/test_auth_api.py | 7 + .../test/test_experimental_api.py | 7 + .../python-legacy/test/test_external_api.py | 7 + .../test/test_external_login_information.py | 36 ++ clients/python/.openapi-generator/FILES | 3 + clients/python/README.md | 4 + clients/python/docs/AuthApi.md | 76 +++++ clients/python/docs/ExperimentalApi.md | 77 +++++ clients/python/docs/ExternalApi.md | 76 +++++ .../python/docs/ExternalLoginInformation.md | 30 ++ clients/python/docs/StsAuthRequest.md | 2 +- clients/python/lakefs_sdk/__init__.py | 1 + clients/python/lakefs_sdk/api/auth_api.py | 150 +++++++++ .../python/lakefs_sdk/api/experimental_api.py | 151 +++++++++ clients/python/lakefs_sdk/api/external_api.py | 151 +++++++++ clients/python/lakefs_sdk/models/__init__.py | 1 + .../models/external_login_information.py | 74 ++++ .../lakefs_sdk/models/sts_auth_request.py | 2 +- clients/python/test/test_auth_api.py | 7 + clients/python/test/test_experimental_api.py | 7 + clients/python/test/test_external_api.py | 7 + .../test/test_external_login_information.py | 57 ++++ cmd/lakefs/cmd/run.go | 4 +- docs/assets/js/swagger.yml | 52 ++- docs/reference/configuration.md | 10 +- pkg/api/controller.go | 53 ++- pkg/auth/remoteauthenticator/authenticator.go | 2 - pkg/auth/service.go | 32 +- pkg/authentication/errors.go | 2 + .../mock/mock_authentication_client.go | 40 +++ pkg/authentication/service.go | 63 +++- pkg/authentication/service_test.go | 26 +- pkg/config/config.go | 7 +- pkg/config/defaults.go | 1 + 83 files changed, 4358 insertions(+), 61 deletions(-) create mode 100644 clients/java-legacy/docs/ExternalLoginInformation.md create mode 100644 clients/java-legacy/src/main/java/io/lakefs/clients/api/model/ExternalLoginInformation.java create mode 100644 clients/java-legacy/src/test/java/io/lakefs/clients/api/model/ExternalLoginInformationTest.java create mode 100644 clients/java/docs/ExternalLoginInformation.md create mode 100644 clients/java/src/main/java/io/lakefs/clients/sdk/model/ExternalLoginInformation.java create mode 100644 clients/java/src/test/java/io/lakefs/clients/sdk/model/ExternalLoginInformationTest.java create mode 100644 clients/python-legacy/docs/ExternalLoginInformation.md create mode 100644 clients/python-legacy/lakefs_client/model/external_login_information.py create mode 100644 clients/python-legacy/test/test_external_login_information.py create mode 100644 clients/python/docs/ExternalLoginInformation.md create mode 100644 clients/python/lakefs_sdk/models/external_login_information.py create mode 100644 clients/python/test/test_external_login_information.py diff --git a/api/authentication.yml b/api/authentication.yml index 2b8200685fe..debbfd46fbd 100644 --- a/api/authentication.yml +++ b/api/authentication.yml @@ -72,12 +72,24 @@ components: type: string responses: + BadRequest: + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" Unauthorized: description: Unauthorized content: application/json: schema: $ref: "#/components/schemas/Error" + Forbidden: + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Error" ServerError: description: Internal Server Error content: @@ -280,6 +292,9 @@ components: external_user_identifier: type: string description: external_user_identifier is the user DN in LDAP set if user exists with that username and has this password. + IdentityRequest: + type: object + StsAuthRequest: type: object required: @@ -303,6 +318,15 @@ components: additionalProperties: type: string description: the claims of the token returned from the provider + + ExternalPrincipal: + type: object + required: + - id + properties: + id: + type: string + paths: /ldap/login: post: @@ -328,6 +352,40 @@ paths: $ref: "#/components/responses/Unauthorized" default: $ref: "#/components/responses/ServerError" + + /auth/external/principal/login: + post: + tags: + - auth + - external + operationId: externalPrincipalLogin + summary: perform a login using an external authenticator + security: [ ] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/IdentityRequest" + responses: + 200: + description: successful external login + content: + application/json: + schema: + $ref: "#/components/schemas/ExternalPrincipal" + 400: + $ref: "#/components/responses/BadRequest" + 401: + $ref: "#/components/responses/Unauthorized" + 403: + $ref: "#/components/responses/Forbidden" + 404: + $ref: "#/components/responses/NotFound" + 420: + description: too many requests + default: + $ref: "#/components/responses/ServerError" + /sts/login: post: tags: diff --git a/api/swagger.yml b/api/swagger.yml index f074dfa38fe..fb011a03ac0 100644 --- a/api/swagger.yml +++ b/api/swagger.yml @@ -38,6 +38,7 @@ components: type: apiKey in: cookie name: saml_auth_session + parameters: PaginationPrefix: in: query @@ -1049,6 +1050,17 @@ components: type: string secret_access_key: type: string + + ExternalLoginInformation: + type: object + required: + - identityRequest + properties: + token_expiration_duration: + type: integer + identityRequest: + type: object + StsAuthRequest: type: object required: @@ -1066,8 +1078,8 @@ components: type: integer format: int64 description: | - The time-to-live for the generated token in seconds. The maximum - value is 3600 seconds (1 hour) max is 12 hours. + The time-to-live for the generated token in seconds. The default + value is 3600 seconds (1 hour) maximum time allowed is 12 hours. AuthenticationToken: type: object required: @@ -1820,6 +1832,41 @@ paths: description: too many requests default: $ref: "#/components/responses/ServerError" + + /auth/external/principal/login: + post: + tags: + - external + - experimental + - auth + operationId: externalPrincipalLogin + summary: perform a login using an external authenticator + security: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ExternalLoginInformation" + responses: + 200: + description: successful external login + content: + application/json: + schema: + $ref: "#/components/schemas/AuthenticationToken" + 400: + $ref: "#/components/responses/BadRequest" + 401: + $ref: "#/components/responses/Unauthorized" + 403: + $ref: "#/components/responses/Forbidden" + 404: + $ref: "#/components/responses/NotFound" + 420: + description: too many requests + default: + $ref: "#/components/responses/ServerError" + /sts/login: post: tags: @@ -1842,10 +1889,11 @@ paths: $ref: "#/components/schemas/AuthenticationToken" 401: $ref: "#/components/responses/Unauthorized" + 420: + description: too many requests default: $ref: "#/components/responses/ServerError" - /auth/capabilities: get: tags: diff --git a/clients/java-legacy/.openapi-generator/FILES b/clients/java-legacy/.openapi-generator/FILES index 392ee20a246..73adf701c38 100644 --- a/clients/java-legacy/.openapi-generator/FILES +++ b/clients/java-legacy/.openapi-generator/FILES @@ -37,6 +37,7 @@ docs/Error.md docs/ErrorNoACL.md docs/ExperimentalApi.md docs/ExternalApi.md +docs/ExternalLoginInformation.md docs/ExternalPrincipal.md docs/ExternalPrincipalCreation.md docs/ExternalPrincipalList.md @@ -186,6 +187,7 @@ src/main/java/io/lakefs/clients/api/model/Diff.java src/main/java/io/lakefs/clients/api/model/DiffList.java src/main/java/io/lakefs/clients/api/model/Error.java src/main/java/io/lakefs/clients/api/model/ErrorNoACL.java +src/main/java/io/lakefs/clients/api/model/ExternalLoginInformation.java src/main/java/io/lakefs/clients/api/model/ExternalPrincipal.java src/main/java/io/lakefs/clients/api/model/ExternalPrincipalCreation.java src/main/java/io/lakefs/clients/api/model/ExternalPrincipalList.java @@ -300,6 +302,7 @@ src/test/java/io/lakefs/clients/api/model/DiffListTest.java src/test/java/io/lakefs/clients/api/model/DiffTest.java src/test/java/io/lakefs/clients/api/model/ErrorNoACLTest.java src/test/java/io/lakefs/clients/api/model/ErrorTest.java +src/test/java/io/lakefs/clients/api/model/ExternalLoginInformationTest.java src/test/java/io/lakefs/clients/api/model/ExternalPrincipalCreationTest.java src/test/java/io/lakefs/clients/api/model/ExternalPrincipalListTest.java src/test/java/io/lakefs/clients/api/model/ExternalPrincipalTest.java diff --git a/clients/java-legacy/README.md b/clients/java-legacy/README.md index cfaf83be69c..8043f90c992 100644 --- a/clients/java-legacy/README.md +++ b/clients/java-legacy/README.md @@ -155,6 +155,7 @@ Class | Method | HTTP request | Description *AuthApi* | [**deleteUserExternalPrincipal**](docs/AuthApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user *AuthApi* | [**detachPolicyFromGroup**](docs/AuthApi.md#detachPolicyFromGroup) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group *AuthApi* | [**detachPolicyFromUser**](docs/AuthApi.md#detachPolicyFromUser) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user +*AuthApi* | [**externalPrincipalLogin**](docs/AuthApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator *AuthApi* | [**getCredentials**](docs/AuthApi.md#getCredentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials *AuthApi* | [**getCurrentUser**](docs/AuthApi.md#getCurrentUser) | **GET** /user | get current user *AuthApi* | [**getExternalPrincipal**](docs/AuthApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id @@ -190,12 +191,14 @@ Class | Method | HTTP request | Description *ExperimentalApi* | [**createPresignMultipartUpload**](docs/ExperimentalApi.md#createPresignMultipartUpload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload *ExperimentalApi* | [**createUserExternalPrincipal**](docs/ExperimentalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExperimentalApi* | [**deleteUserExternalPrincipal**](docs/ExperimentalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExperimentalApi* | [**externalPrincipalLogin**](docs/ExperimentalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExperimentalApi* | [**getExternalPrincipal**](docs/ExperimentalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id *ExperimentalApi* | [**hardResetBranch**](docs/ExperimentalApi.md#hardResetBranch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch *ExperimentalApi* | [**listUserExternalPrincipals**](docs/ExperimentalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *ExperimentalApi* | [**stsLogin**](docs/ExperimentalApi.md#stsLogin) | **POST** /sts/login | perform a login with STS *ExternalApi* | [**createUserExternalPrincipal**](docs/ExternalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExternalApi* | [**deleteUserExternalPrincipal**](docs/ExternalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExternalApi* | [**externalPrincipalLogin**](docs/ExternalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExternalApi* | [**getExternalPrincipal**](docs/ExternalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id *ExternalApi* | [**listUserExternalPrincipals**](docs/ExternalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *HealthCheckApi* | [**healthCheck**](docs/HealthCheckApi.md#healthCheck) | **GET** /healthcheck | @@ -293,6 +296,7 @@ Class | Method | HTTP request | Description - [DiffList](docs/DiffList.md) - [Error](docs/Error.md) - [ErrorNoACL](docs/ErrorNoACL.md) + - [ExternalLoginInformation](docs/ExternalLoginInformation.md) - [ExternalPrincipal](docs/ExternalPrincipal.md) - [ExternalPrincipalCreation](docs/ExternalPrincipalCreation.md) - [ExternalPrincipalList](docs/ExternalPrincipalList.md) diff --git a/clients/java-legacy/api/openapi.yaml b/clients/java-legacy/api/openapi.yaml index 16ef31f0d8c..98ec6b1c984 100644 --- a/clients/java-legacy/api/openapi.yaml +++ b/clients/java-legacy/api/openapi.yaml @@ -174,6 +174,61 @@ paths: - auth x-contentType: application/json x-accepts: application/json + /auth/external/principal/login: + post: + operationId: externalPrincipalLogin + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalLoginInformation' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/AuthenticationToken' + description: successful external login + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Bad Request + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Forbidden + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Resource Not Found + "420": + description: too many requests + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Internal Server Error + security: [] + summary: perform a login using an external authenticator + tags: + - external + - experimental + - auth + x-contentType: application/json + x-accepts: application/json /sts/login: post: operationId: stsLogin @@ -196,6 +251,8 @@ paths: schema: $ref: '#/components/schemas/Error' description: Unauthorized + "420": + description: too many requests default: content: application/json: @@ -8174,6 +8231,18 @@ components: - access_key_id - secret_access_key type: object + ExternalLoginInformation: + example: + identityRequest: '{}' + token_expiration_duration: 0 + properties: + token_expiration_duration: + type: integer + identityRequest: + type: object + required: + - identityRequest + type: object StsAuthRequest: example: code: code @@ -8189,8 +8258,8 @@ components: type: string ttl_seconds: description: | - The time-to-live for the generated token in seconds. The maximum - value is 3600 seconds (1 hour) max is 12 hours. + The time-to-live for the generated token in seconds. The default + value is 3600 seconds (1 hour) maximum time allowed is 12 hours. format: int64 type: integer required: diff --git a/clients/java-legacy/docs/AuthApi.md b/clients/java-legacy/docs/AuthApi.md index b6308ae3dd4..536fd454137 100644 --- a/clients/java-legacy/docs/AuthApi.md +++ b/clients/java-legacy/docs/AuthApi.md @@ -20,6 +20,7 @@ Method | HTTP request | Description [**deleteUserExternalPrincipal**](AuthApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user [**detachPolicyFromGroup**](AuthApi.md#detachPolicyFromGroup) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group [**detachPolicyFromUser**](AuthApi.md#detachPolicyFromUser) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user +[**externalPrincipalLogin**](AuthApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**getCredentials**](AuthApi.md#getCredentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials [**getCurrentUser**](AuthApi.md#getCurrentUser) | **GET** /user | get current user [**getExternalPrincipal**](AuthApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id @@ -1524,6 +1525,72 @@ null (empty response body) **420** | too many requests | - | **0** | Internal Server Error | - | + +# **externalPrincipalLogin** +> AuthenticationToken externalPrincipalLogin(externalLoginInformation) + +perform a login using an external authenticator + +### Example +```java +// Import classes: +import io.lakefs.clients.api.ApiClient; +import io.lakefs.clients.api.ApiException; +import io.lakefs.clients.api.Configuration; +import io.lakefs.clients.api.models.*; +import io.lakefs.clients.api.AuthApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("http://localhost/api/v1"); + + AuthApi apiInstance = new AuthApi(defaultClient); + ExternalLoginInformation externalLoginInformation = new ExternalLoginInformation(); // ExternalLoginInformation | + try { + AuthenticationToken result = apiInstance.externalPrincipalLogin(externalLoginInformation); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling AuthApi#externalPrincipalLogin"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **externalLoginInformation** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + # **getCredentials** > Credentials getCredentials(userId, accessKeyId) diff --git a/clients/java-legacy/docs/ExperimentalApi.md b/clients/java-legacy/docs/ExperimentalApi.md index e79d83e9f85..251f557b7b3 100644 --- a/clients/java-legacy/docs/ExperimentalApi.md +++ b/clients/java-legacy/docs/ExperimentalApi.md @@ -9,6 +9,7 @@ Method | HTTP request | Description [**createPresignMultipartUpload**](ExperimentalApi.md#createPresignMultipartUpload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload [**createUserExternalPrincipal**](ExperimentalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user [**deleteUserExternalPrincipal**](ExperimentalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +[**externalPrincipalLogin**](ExperimentalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**getExternalPrincipal**](ExperimentalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id [**hardResetBranch**](ExperimentalApi.md#hardResetBranch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch [**listUserExternalPrincipals**](ExperimentalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user @@ -511,6 +512,72 @@ null (empty response body) **420** | too many requests | - | **0** | Internal Server Error | - | + +# **externalPrincipalLogin** +> AuthenticationToken externalPrincipalLogin(externalLoginInformation) + +perform a login using an external authenticator + +### Example +```java +// Import classes: +import io.lakefs.clients.api.ApiClient; +import io.lakefs.clients.api.ApiException; +import io.lakefs.clients.api.Configuration; +import io.lakefs.clients.api.models.*; +import io.lakefs.clients.api.ExperimentalApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("http://localhost/api/v1"); + + ExperimentalApi apiInstance = new ExperimentalApi(defaultClient); + ExternalLoginInformation externalLoginInformation = new ExternalLoginInformation(); // ExternalLoginInformation | + try { + AuthenticationToken result = apiInstance.externalPrincipalLogin(externalLoginInformation); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling ExperimentalApi#externalPrincipalLogin"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **externalLoginInformation** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + # **getExternalPrincipal** > ExternalPrincipal getExternalPrincipal(principalId) @@ -862,5 +929,6 @@ No authorization required |-------------|-------------|------------------| **200** | successful STS login | - | **401** | Unauthorized | - | +**420** | too many requests | - | **0** | Internal Server Error | - | diff --git a/clients/java-legacy/docs/ExternalApi.md b/clients/java-legacy/docs/ExternalApi.md index 889c53a83f4..01e917d344a 100644 --- a/clients/java-legacy/docs/ExternalApi.md +++ b/clients/java-legacy/docs/ExternalApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**createUserExternalPrincipal**](ExternalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user [**deleteUserExternalPrincipal**](ExternalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +[**externalPrincipalLogin**](ExternalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**getExternalPrincipal**](ExternalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id [**listUserExternalPrincipals**](ExternalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user @@ -199,6 +200,72 @@ null (empty response body) **420** | too many requests | - | **0** | Internal Server Error | - | + +# **externalPrincipalLogin** +> AuthenticationToken externalPrincipalLogin(externalLoginInformation) + +perform a login using an external authenticator + +### Example +```java +// Import classes: +import io.lakefs.clients.api.ApiClient; +import io.lakefs.clients.api.ApiException; +import io.lakefs.clients.api.Configuration; +import io.lakefs.clients.api.models.*; +import io.lakefs.clients.api.ExternalApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("http://localhost/api/v1"); + + ExternalApi apiInstance = new ExternalApi(defaultClient); + ExternalLoginInformation externalLoginInformation = new ExternalLoginInformation(); // ExternalLoginInformation | + try { + AuthenticationToken result = apiInstance.externalPrincipalLogin(externalLoginInformation); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling ExternalApi#externalPrincipalLogin"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **externalLoginInformation** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + # **getExternalPrincipal** > ExternalPrincipal getExternalPrincipal(principalId) diff --git a/clients/java-legacy/docs/ExternalLoginInformation.md b/clients/java-legacy/docs/ExternalLoginInformation.md new file mode 100644 index 00000000000..a5a627e1924 --- /dev/null +++ b/clients/java-legacy/docs/ExternalLoginInformation.md @@ -0,0 +1,14 @@ + + +# ExternalLoginInformation + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**tokenExpirationDuration** | **Integer** | | [optional] +**identityRequest** | **Object** | | + + + diff --git a/clients/java-legacy/docs/StsAuthRequest.md b/clients/java-legacy/docs/StsAuthRequest.md index ee58c5376c9..fa6d915593e 100644 --- a/clients/java-legacy/docs/StsAuthRequest.md +++ b/clients/java-legacy/docs/StsAuthRequest.md @@ -10,7 +10,7 @@ Name | Type | Description | Notes **code** | **String** | | **state** | **String** | | **redirectUri** | **String** | | -**ttlSeconds** | **Long** | The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. | [optional] +**ttlSeconds** | **Long** | The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. | [optional] diff --git a/clients/java-legacy/src/main/java/io/lakefs/clients/api/AuthApi.java b/clients/java-legacy/src/main/java/io/lakefs/clients/api/AuthApi.java index f17d4f8483c..585ef6add21 100644 --- a/clients/java-legacy/src/main/java/io/lakefs/clients/api/AuthApi.java +++ b/clients/java-legacy/src/main/java/io/lakefs/clients/api/AuthApi.java @@ -35,6 +35,7 @@ import io.lakefs.clients.api.model.CurrentUser; import io.lakefs.clients.api.model.Error; import io.lakefs.clients.api.model.ErrorNoACL; +import io.lakefs.clients.api.model.ExternalLoginInformation; import io.lakefs.clients.api.model.ExternalPrincipal; import io.lakefs.clients.api.model.ExternalPrincipalCreation; import io.lakefs.clients.api.model.ExternalPrincipalList; @@ -2172,6 +2173,136 @@ public okhttp3.Call detachPolicyFromUserAsync(String userId, String policyId, fi localVarApiClient.executeAsync(localVarCall, _callback); return localVarCall; } + /** + * Build call for externalPrincipalLogin + * @param externalLoginInformation (optional) + * @param _callback Callback for upload/download progress + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call externalPrincipalLoginCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + Object localVarPostBody = externalLoginInformation; + + // create path and map variables + String localVarPath = "/auth/external/principal/login"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + localVarHeaderParams.put("Content-Type", localVarContentType); + + String[] localVarAuthNames = new String[] { }; + return localVarApiClient.buildCall(localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + @SuppressWarnings("rawtypes") + private okhttp3.Call externalPrincipalLoginValidateBeforeCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + + okhttp3.Call localVarCall = externalPrincipalLoginCall(externalLoginInformation, _callback); + return localVarCall; + + } + + /** + * perform a login using an external authenticator + * + * @param externalLoginInformation (optional) + * @return AuthenticationToken + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public AuthenticationToken externalPrincipalLogin(ExternalLoginInformation externalLoginInformation) throws ApiException { + ApiResponse localVarResp = externalPrincipalLoginWithHttpInfo(externalLoginInformation); + return localVarResp.getData(); + } + + /** + * perform a login using an external authenticator + * + * @param externalLoginInformation (optional) + * @return ApiResponse<AuthenticationToken> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public ApiResponse externalPrincipalLoginWithHttpInfo(ExternalLoginInformation externalLoginInformation) throws ApiException { + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, null); + Type localVarReturnType = new TypeToken(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + } + + /** + * perform a login using an external authenticator (asynchronously) + * + * @param externalLoginInformation (optional) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call externalPrincipalLoginAsync(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, _callback); + Type localVarReturnType = new TypeToken(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback); + return localVarCall; + } /** * Build call for getCredentials * @param userId (required) diff --git a/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExperimentalApi.java b/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExperimentalApi.java index 3a2090dfa73..af8b8656512 100644 --- a/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExperimentalApi.java +++ b/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExperimentalApi.java @@ -31,6 +31,7 @@ import io.lakefs.clients.api.model.AuthenticationToken; import io.lakefs.clients.api.model.CompletePresignMultipartUpload; import io.lakefs.clients.api.model.Error; +import io.lakefs.clients.api.model.ExternalLoginInformation; import io.lakefs.clients.api.model.ExternalPrincipal; import io.lakefs.clients.api.model.ExternalPrincipalCreation; import io.lakefs.clients.api.model.ExternalPrincipalList; @@ -847,6 +848,136 @@ public okhttp3.Call deleteUserExternalPrincipalAsync(String userId, String princ localVarApiClient.executeAsync(localVarCall, _callback); return localVarCall; } + /** + * Build call for externalPrincipalLogin + * @param externalLoginInformation (optional) + * @param _callback Callback for upload/download progress + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call externalPrincipalLoginCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + Object localVarPostBody = externalLoginInformation; + + // create path and map variables + String localVarPath = "/auth/external/principal/login"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + localVarHeaderParams.put("Content-Type", localVarContentType); + + String[] localVarAuthNames = new String[] { }; + return localVarApiClient.buildCall(localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + @SuppressWarnings("rawtypes") + private okhttp3.Call externalPrincipalLoginValidateBeforeCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + + okhttp3.Call localVarCall = externalPrincipalLoginCall(externalLoginInformation, _callback); + return localVarCall; + + } + + /** + * perform a login using an external authenticator + * + * @param externalLoginInformation (optional) + * @return AuthenticationToken + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public AuthenticationToken externalPrincipalLogin(ExternalLoginInformation externalLoginInformation) throws ApiException { + ApiResponse localVarResp = externalPrincipalLoginWithHttpInfo(externalLoginInformation); + return localVarResp.getData(); + } + + /** + * perform a login using an external authenticator + * + * @param externalLoginInformation (optional) + * @return ApiResponse<AuthenticationToken> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public ApiResponse externalPrincipalLoginWithHttpInfo(ExternalLoginInformation externalLoginInformation) throws ApiException { + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, null); + Type localVarReturnType = new TypeToken(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + } + + /** + * perform a login using an external authenticator (asynchronously) + * + * @param externalLoginInformation (optional) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call externalPrincipalLoginAsync(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, _callback); + Type localVarReturnType = new TypeToken(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback); + return localVarCall; + } /** * Build call for getExternalPrincipal * @param principalId (required) @@ -1304,6 +1435,7 @@ public okhttp3.Call listUserExternalPrincipalsAsync(String userId, String prefix Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ @@ -1362,6 +1494,7 @@ private okhttp3.Call stsLoginValidateBeforeCall(StsAuthRequest stsAuthRequest, f Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ @@ -1381,6 +1514,7 @@ public AuthenticationToken stsLogin(StsAuthRequest stsAuthRequest) throws ApiExc Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ @@ -1402,6 +1536,7 @@ public ApiResponse stsLoginWithHttpInfo(StsAuthRequest stsA Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ diff --git a/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExternalApi.java b/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExternalApi.java index d55305caf94..1200d0ca666 100644 --- a/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExternalApi.java +++ b/clients/java-legacy/src/main/java/io/lakefs/clients/api/ExternalApi.java @@ -27,7 +27,9 @@ import java.io.IOException; +import io.lakefs.clients.api.model.AuthenticationToken; import io.lakefs.clients.api.model.Error; +import io.lakefs.clients.api.model.ExternalLoginInformation; import io.lakefs.clients.api.model.ExternalPrincipal; import io.lakefs.clients.api.model.ExternalPrincipalCreation; import io.lakefs.clients.api.model.ExternalPrincipalList; @@ -339,6 +341,136 @@ public okhttp3.Call deleteUserExternalPrincipalAsync(String userId, String princ localVarApiClient.executeAsync(localVarCall, _callback); return localVarCall; } + /** + * Build call for externalPrincipalLogin + * @param externalLoginInformation (optional) + * @param _callback Callback for upload/download progress + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call externalPrincipalLoginCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + Object localVarPostBody = externalLoginInformation; + + // create path and map variables + String localVarPath = "/auth/external/principal/login"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + localVarHeaderParams.put("Content-Type", localVarContentType); + + String[] localVarAuthNames = new String[] { }; + return localVarApiClient.buildCall(localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + @SuppressWarnings("rawtypes") + private okhttp3.Call externalPrincipalLoginValidateBeforeCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + + okhttp3.Call localVarCall = externalPrincipalLoginCall(externalLoginInformation, _callback); + return localVarCall; + + } + + /** + * perform a login using an external authenticator + * + * @param externalLoginInformation (optional) + * @return AuthenticationToken + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public AuthenticationToken externalPrincipalLogin(ExternalLoginInformation externalLoginInformation) throws ApiException { + ApiResponse localVarResp = externalPrincipalLoginWithHttpInfo(externalLoginInformation); + return localVarResp.getData(); + } + + /** + * perform a login using an external authenticator + * + * @param externalLoginInformation (optional) + * @return ApiResponse<AuthenticationToken> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public ApiResponse externalPrincipalLoginWithHttpInfo(ExternalLoginInformation externalLoginInformation) throws ApiException { + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, null); + Type localVarReturnType = new TypeToken(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + } + + /** + * perform a login using an external authenticator (asynchronously) + * + * @param externalLoginInformation (optional) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call externalPrincipalLoginAsync(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, _callback); + Type localVarReturnType = new TypeToken(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback); + return localVarCall; + } /** * Build call for getExternalPrincipal * @param principalId (required) diff --git a/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/ExternalLoginInformation.java b/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/ExternalLoginInformation.java new file mode 100644 index 00000000000..cf7d223137c --- /dev/null +++ b/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/ExternalLoginInformation.java @@ -0,0 +1,127 @@ +/* + * lakeFS API + * lakeFS HTTP API + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package io.lakefs.clients.api.model; + +import java.util.Objects; +import java.util.Arrays; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.IOException; + +/** + * ExternalLoginInformation + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class ExternalLoginInformation { + public static final String SERIALIZED_NAME_TOKEN_EXPIRATION_DURATION = "token_expiration_duration"; + @SerializedName(SERIALIZED_NAME_TOKEN_EXPIRATION_DURATION) + private Integer tokenExpirationDuration; + + public static final String SERIALIZED_NAME_IDENTITY_REQUEST = "identityRequest"; + @SerializedName(SERIALIZED_NAME_IDENTITY_REQUEST) + private Object identityRequest; + + + public ExternalLoginInformation tokenExpirationDuration(Integer tokenExpirationDuration) { + + this.tokenExpirationDuration = tokenExpirationDuration; + return this; + } + + /** + * Get tokenExpirationDuration + * @return tokenExpirationDuration + **/ + @javax.annotation.Nullable + @ApiModelProperty(value = "") + + public Integer getTokenExpirationDuration() { + return tokenExpirationDuration; + } + + + public void setTokenExpirationDuration(Integer tokenExpirationDuration) { + this.tokenExpirationDuration = tokenExpirationDuration; + } + + + public ExternalLoginInformation identityRequest(Object identityRequest) { + + this.identityRequest = identityRequest; + return this; + } + + /** + * Get identityRequest + * @return identityRequest + **/ + @javax.annotation.Nonnull + @ApiModelProperty(required = true, value = "") + + public Object getIdentityRequest() { + return identityRequest; + } + + + public void setIdentityRequest(Object identityRequest) { + this.identityRequest = identityRequest; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ExternalLoginInformation externalLoginInformation = (ExternalLoginInformation) o; + return Objects.equals(this.tokenExpirationDuration, externalLoginInformation.tokenExpirationDuration) && + Objects.equals(this.identityRequest, externalLoginInformation.identityRequest); + } + + @Override + public int hashCode() { + return Objects.hash(tokenExpirationDuration, identityRequest); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ExternalLoginInformation {\n"); + sb.append(" tokenExpirationDuration: ").append(toIndentedString(tokenExpirationDuration)).append("\n"); + sb.append(" identityRequest: ").append(toIndentedString(identityRequest)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StsAuthRequest.java b/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StsAuthRequest.java index 18be384d5c5..38bac11faf1 100644 --- a/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StsAuthRequest.java +++ b/clients/java-legacy/src/main/java/io/lakefs/clients/api/model/StsAuthRequest.java @@ -122,11 +122,11 @@ public StsAuthRequest ttlSeconds(Long ttlSeconds) { } /** - * The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. + * The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. * @return ttlSeconds **/ @javax.annotation.Nullable - @ApiModelProperty(value = "The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. ") + @ApiModelProperty(value = "The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. ") public Long getTtlSeconds() { return ttlSeconds; diff --git a/clients/java-legacy/src/test/java/io/lakefs/clients/api/AuthApiTest.java b/clients/java-legacy/src/test/java/io/lakefs/clients/api/AuthApiTest.java index aff3996512e..1ffe4a11ce9 100644 --- a/clients/java-legacy/src/test/java/io/lakefs/clients/api/AuthApiTest.java +++ b/clients/java-legacy/src/test/java/io/lakefs/clients/api/AuthApiTest.java @@ -22,6 +22,7 @@ import io.lakefs.clients.api.model.CurrentUser; import io.lakefs.clients.api.model.Error; import io.lakefs.clients.api.model.ErrorNoACL; +import io.lakefs.clients.api.model.ExternalLoginInformation; import io.lakefs.clients.api.model.ExternalPrincipal; import io.lakefs.clients.api.model.ExternalPrincipalCreation; import io.lakefs.clients.api.model.ExternalPrincipalList; @@ -301,6 +302,21 @@ public void detachPolicyFromUserTest() throws ApiException { // TODO: test validations } + /** + * perform a login using an external authenticator + * + * + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void externalPrincipalLoginTest() throws ApiException { + ExternalLoginInformation externalLoginInformation = null; + AuthenticationToken response = api.externalPrincipalLogin(externalLoginInformation); + // TODO: test validations + } + /** * get credentials * diff --git a/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExperimentalApiTest.java b/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExperimentalApiTest.java index b293da228d0..7de9cabd387 100644 --- a/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExperimentalApiTest.java +++ b/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExperimentalApiTest.java @@ -18,6 +18,7 @@ import io.lakefs.clients.api.model.AuthenticationToken; import io.lakefs.clients.api.model.CompletePresignMultipartUpload; import io.lakefs.clients.api.model.Error; +import io.lakefs.clients.api.model.ExternalLoginInformation; import io.lakefs.clients.api.model.ExternalPrincipal; import io.lakefs.clients.api.model.ExternalPrincipalCreation; import io.lakefs.clients.api.model.ExternalPrincipalList; @@ -131,6 +132,21 @@ public void deleteUserExternalPrincipalTest() throws ApiException { // TODO: test validations } + /** + * perform a login using an external authenticator + * + * + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void externalPrincipalLoginTest() throws ApiException { + ExternalLoginInformation externalLoginInformation = null; + AuthenticationToken response = api.externalPrincipalLogin(externalLoginInformation); + // TODO: test validations + } + /** * describe external principal by id * diff --git a/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExternalApiTest.java b/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExternalApiTest.java index 09ec5293332..b9f14c69650 100644 --- a/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExternalApiTest.java +++ b/clients/java-legacy/src/test/java/io/lakefs/clients/api/ExternalApiTest.java @@ -14,7 +14,9 @@ package io.lakefs.clients.api; import io.lakefs.clients.api.ApiException; +import io.lakefs.clients.api.model.AuthenticationToken; import io.lakefs.clients.api.model.Error; +import io.lakefs.clients.api.model.ExternalLoginInformation; import io.lakefs.clients.api.model.ExternalPrincipal; import io.lakefs.clients.api.model.ExternalPrincipalCreation; import io.lakefs.clients.api.model.ExternalPrincipalList; @@ -68,6 +70,21 @@ public void deleteUserExternalPrincipalTest() throws ApiException { // TODO: test validations } + /** + * perform a login using an external authenticator + * + * + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void externalPrincipalLoginTest() throws ApiException { + ExternalLoginInformation externalLoginInformation = null; + AuthenticationToken response = api.externalPrincipalLogin(externalLoginInformation); + // TODO: test validations + } + /** * describe external principal by id * diff --git a/clients/java-legacy/src/test/java/io/lakefs/clients/api/model/ExternalLoginInformationTest.java b/clients/java-legacy/src/test/java/io/lakefs/clients/api/model/ExternalLoginInformationTest.java new file mode 100644 index 00000000000..87e3a49590d --- /dev/null +++ b/clients/java-legacy/src/test/java/io/lakefs/clients/api/model/ExternalLoginInformationTest.java @@ -0,0 +1,59 @@ +/* + * lakeFS API + * lakeFS HTTP API + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package io.lakefs.clients.api.model; + +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.IOException; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + + +/** + * Model tests for ExternalLoginInformation + */ +public class ExternalLoginInformationTest { + private final ExternalLoginInformation model = new ExternalLoginInformation(); + + /** + * Model tests for ExternalLoginInformation + */ + @Test + public void testExternalLoginInformation() { + // TODO: test ExternalLoginInformation + } + + /** + * Test the property 'tokenExpirationDuration' + */ + @Test + public void tokenExpirationDurationTest() { + // TODO: test tokenExpirationDuration + } + + /** + * Test the property 'identityRequest' + */ + @Test + public void identityRequestTest() { + // TODO: test identityRequest + } + +} diff --git a/clients/java/README.md b/clients/java/README.md index 205c95be9db..3953f80aa60 100644 --- a/clients/java/README.md +++ b/clients/java/README.md @@ -163,6 +163,7 @@ Class | Method | HTTP request | Description *AuthApi* | [**deleteUserExternalPrincipal**](docs/AuthApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user *AuthApi* | [**detachPolicyFromGroup**](docs/AuthApi.md#detachPolicyFromGroup) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group *AuthApi* | [**detachPolicyFromUser**](docs/AuthApi.md#detachPolicyFromUser) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user +*AuthApi* | [**externalPrincipalLogin**](docs/AuthApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator *AuthApi* | [**getCredentials**](docs/AuthApi.md#getCredentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials *AuthApi* | [**getCurrentUser**](docs/AuthApi.md#getCurrentUser) | **GET** /user | get current user *AuthApi* | [**getExternalPrincipal**](docs/AuthApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id @@ -198,12 +199,14 @@ Class | Method | HTTP request | Description *ExperimentalApi* | [**createPresignMultipartUpload**](docs/ExperimentalApi.md#createPresignMultipartUpload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload *ExperimentalApi* | [**createUserExternalPrincipal**](docs/ExperimentalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExperimentalApi* | [**deleteUserExternalPrincipal**](docs/ExperimentalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExperimentalApi* | [**externalPrincipalLogin**](docs/ExperimentalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExperimentalApi* | [**getExternalPrincipal**](docs/ExperimentalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id *ExperimentalApi* | [**hardResetBranch**](docs/ExperimentalApi.md#hardResetBranch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch *ExperimentalApi* | [**listUserExternalPrincipals**](docs/ExperimentalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *ExperimentalApi* | [**stsLogin**](docs/ExperimentalApi.md#stsLogin) | **POST** /sts/login | perform a login with STS *ExternalApi* | [**createUserExternalPrincipal**](docs/ExternalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExternalApi* | [**deleteUserExternalPrincipal**](docs/ExternalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExternalApi* | [**externalPrincipalLogin**](docs/ExternalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExternalApi* | [**getExternalPrincipal**](docs/ExternalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id *ExternalApi* | [**listUserExternalPrincipals**](docs/ExternalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *HealthCheckApi* | [**healthCheck**](docs/HealthCheckApi.md#healthCheck) | **GET** /healthcheck | @@ -301,6 +304,7 @@ Class | Method | HTTP request | Description - [DiffList](docs/DiffList.md) - [Error](docs/Error.md) - [ErrorNoACL](docs/ErrorNoACL.md) + - [ExternalLoginInformation](docs/ExternalLoginInformation.md) - [ExternalPrincipal](docs/ExternalPrincipal.md) - [ExternalPrincipalCreation](docs/ExternalPrincipalCreation.md) - [ExternalPrincipalList](docs/ExternalPrincipalList.md) diff --git a/clients/java/api/openapi.yaml b/clients/java/api/openapi.yaml index 195ab74d731..db50fed50a2 100644 --- a/clients/java/api/openapi.yaml +++ b/clients/java/api/openapi.yaml @@ -174,6 +174,61 @@ paths: - auth x-content-type: application/json x-accepts: application/json + /auth/external/principal/login: + post: + operationId: externalPrincipalLogin + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalLoginInformation' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/AuthenticationToken' + description: successful external login + "400": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Bad Request + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Unauthorized + "403": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Forbidden + "404": + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Resource Not Found + "420": + description: too many requests + default: + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + description: Internal Server Error + security: [] + summary: perform a login using an external authenticator + tags: + - external + - experimental + - auth + x-content-type: application/json + x-accepts: application/json /sts/login: post: operationId: stsLogin @@ -196,6 +251,8 @@ paths: schema: $ref: '#/components/schemas/Error' description: Unauthorized + "420": + description: too many requests default: content: application/json: @@ -8148,6 +8205,18 @@ components: - access_key_id - secret_access_key type: object + ExternalLoginInformation: + example: + identityRequest: "{}" + token_expiration_duration: 0 + properties: + token_expiration_duration: + type: integer + identityRequest: + type: object + required: + - identityRequest + type: object StsAuthRequest: example: code: code @@ -8163,8 +8232,8 @@ components: type: string ttl_seconds: description: | - The time-to-live for the generated token in seconds. The maximum - value is 3600 seconds (1 hour) max is 12 hours. + The time-to-live for the generated token in seconds. The default + value is 3600 seconds (1 hour) maximum time allowed is 12 hours. format: int64 type: integer required: diff --git a/clients/java/docs/AuthApi.md b/clients/java/docs/AuthApi.md index febab38cd46..b5c34ea6849 100644 --- a/clients/java/docs/AuthApi.md +++ b/clients/java/docs/AuthApi.md @@ -20,6 +20,7 @@ All URIs are relative to */api/v1* | [**deleteUserExternalPrincipal**](AuthApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user | | [**detachPolicyFromGroup**](AuthApi.md#detachPolicyFromGroup) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group | | [**detachPolicyFromUser**](AuthApi.md#detachPolicyFromUser) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user | +| [**externalPrincipalLogin**](AuthApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator | | [**getCredentials**](AuthApi.md#getCredentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials | | [**getCurrentUser**](AuthApi.md#getCurrentUser) | **GET** /user | get current user | | [**getExternalPrincipal**](AuthApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id | @@ -1543,6 +1544,74 @@ null (empty response body) | **420** | too many requests | - | | **0** | Internal Server Error | - | + +# **externalPrincipalLogin** +> AuthenticationToken externalPrincipalLogin().externalLoginInformation(externalLoginInformation).execute(); + +perform a login using an external authenticator + +### Example +```java +// Import classes: +import io.lakefs.clients.sdk.ApiClient; +import io.lakefs.clients.sdk.ApiException; +import io.lakefs.clients.sdk.Configuration; +import io.lakefs.clients.sdk.models.*; +import io.lakefs.clients.sdk.AuthApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("/api/v1"); + + AuthApi apiInstance = new AuthApi(defaultClient); + ExternalLoginInformation externalLoginInformation = new ExternalLoginInformation(); // ExternalLoginInformation | + try { + AuthenticationToken result = apiInstance.externalPrincipalLogin() + .externalLoginInformation(externalLoginInformation) + .execute(); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling AuthApi#externalPrincipalLogin"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **externalLoginInformation** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] | + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | successful external login | - | +| **400** | Bad Request | - | +| **401** | Unauthorized | - | +| **403** | Forbidden | - | +| **404** | Resource Not Found | - | +| **420** | too many requests | - | +| **0** | Internal Server Error | - | + # **getCredentials** > Credentials getCredentials(userId, accessKeyId).execute(); diff --git a/clients/java/docs/ExperimentalApi.md b/clients/java/docs/ExperimentalApi.md index e9fbde14aa1..fa6c9338b82 100644 --- a/clients/java/docs/ExperimentalApi.md +++ b/clients/java/docs/ExperimentalApi.md @@ -9,6 +9,7 @@ All URIs are relative to */api/v1* | [**createPresignMultipartUpload**](ExperimentalApi.md#createPresignMultipartUpload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload | | [**createUserExternalPrincipal**](ExperimentalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user | | [**deleteUserExternalPrincipal**](ExperimentalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user | +| [**externalPrincipalLogin**](ExperimentalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator | | [**getExternalPrincipal**](ExperimentalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id | | [**hardResetBranch**](ExperimentalApi.md#hardResetBranch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch | | [**listUserExternalPrincipals**](ExperimentalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user | @@ -520,6 +521,74 @@ null (empty response body) | **420** | too many requests | - | | **0** | Internal Server Error | - | + +# **externalPrincipalLogin** +> AuthenticationToken externalPrincipalLogin().externalLoginInformation(externalLoginInformation).execute(); + +perform a login using an external authenticator + +### Example +```java +// Import classes: +import io.lakefs.clients.sdk.ApiClient; +import io.lakefs.clients.sdk.ApiException; +import io.lakefs.clients.sdk.Configuration; +import io.lakefs.clients.sdk.models.*; +import io.lakefs.clients.sdk.ExperimentalApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("/api/v1"); + + ExperimentalApi apiInstance = new ExperimentalApi(defaultClient); + ExternalLoginInformation externalLoginInformation = new ExternalLoginInformation(); // ExternalLoginInformation | + try { + AuthenticationToken result = apiInstance.externalPrincipalLogin() + .externalLoginInformation(externalLoginInformation) + .execute(); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling ExperimentalApi#externalPrincipalLogin"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **externalLoginInformation** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] | + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | successful external login | - | +| **400** | Bad Request | - | +| **401** | Unauthorized | - | +| **403** | Forbidden | - | +| **404** | Resource Not Found | - | +| **420** | too many requests | - | +| **0** | Internal Server Error | - | + # **getExternalPrincipal** > ExternalPrincipal getExternalPrincipal(principalId).execute(); @@ -879,5 +948,6 @@ No authorization required |-------------|-------------|------------------| | **200** | successful STS login | - | | **401** | Unauthorized | - | +| **420** | too many requests | - | | **0** | Internal Server Error | - | diff --git a/clients/java/docs/ExternalApi.md b/clients/java/docs/ExternalApi.md index 7c18c871b5d..ae9e30c06ea 100644 --- a/clients/java/docs/ExternalApi.md +++ b/clients/java/docs/ExternalApi.md @@ -6,6 +6,7 @@ All URIs are relative to */api/v1* |------------- | ------------- | -------------| | [**createUserExternalPrincipal**](ExternalApi.md#createUserExternalPrincipal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user | | [**deleteUserExternalPrincipal**](ExternalApi.md#deleteUserExternalPrincipal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user | +| [**externalPrincipalLogin**](ExternalApi.md#externalPrincipalLogin) | **POST** /auth/external/principal/login | perform a login using an external authenticator | | [**getExternalPrincipal**](ExternalApi.md#getExternalPrincipal) | **GET** /auth/external/principals | describe external principal by id | | [**listUserExternalPrincipals**](ExternalApi.md#listUserExternalPrincipals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user | @@ -202,6 +203,74 @@ null (empty response body) | **420** | too many requests | - | | **0** | Internal Server Error | - | + +# **externalPrincipalLogin** +> AuthenticationToken externalPrincipalLogin().externalLoginInformation(externalLoginInformation).execute(); + +perform a login using an external authenticator + +### Example +```java +// Import classes: +import io.lakefs.clients.sdk.ApiClient; +import io.lakefs.clients.sdk.ApiException; +import io.lakefs.clients.sdk.Configuration; +import io.lakefs.clients.sdk.models.*; +import io.lakefs.clients.sdk.ExternalApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("/api/v1"); + + ExternalApi apiInstance = new ExternalApi(defaultClient); + ExternalLoginInformation externalLoginInformation = new ExternalLoginInformation(); // ExternalLoginInformation | + try { + AuthenticationToken result = apiInstance.externalPrincipalLogin() + .externalLoginInformation(externalLoginInformation) + .execute(); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling ExternalApi#externalPrincipalLogin"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **externalLoginInformation** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] | + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | successful external login | - | +| **400** | Bad Request | - | +| **401** | Unauthorized | - | +| **403** | Forbidden | - | +| **404** | Resource Not Found | - | +| **420** | too many requests | - | +| **0** | Internal Server Error | - | + # **getExternalPrincipal** > ExternalPrincipal getExternalPrincipal(principalId).execute(); diff --git a/clients/java/docs/ExternalLoginInformation.md b/clients/java/docs/ExternalLoginInformation.md new file mode 100644 index 00000000000..4430d03d87a --- /dev/null +++ b/clients/java/docs/ExternalLoginInformation.md @@ -0,0 +1,14 @@ + + +# ExternalLoginInformation + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**tokenExpirationDuration** | **Integer** | | [optional] | +|**identityRequest** | **Object** | | | + + + diff --git a/clients/java/docs/StsAuthRequest.md b/clients/java/docs/StsAuthRequest.md index bf1683b4810..0aec048a03e 100644 --- a/clients/java/docs/StsAuthRequest.md +++ b/clients/java/docs/StsAuthRequest.md @@ -10,7 +10,7 @@ |**code** | **String** | | | |**state** | **String** | | | |**redirectUri** | **String** | | | -|**ttlSeconds** | **Long** | The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. | [optional] | +|**ttlSeconds** | **Long** | The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. | [optional] | diff --git a/clients/java/src/main/java/io/lakefs/clients/sdk/AuthApi.java b/clients/java/src/main/java/io/lakefs/clients/sdk/AuthApi.java index 87deaed69fc..6a7c627c1a4 100644 --- a/clients/java/src/main/java/io/lakefs/clients/sdk/AuthApi.java +++ b/clients/java/src/main/java/io/lakefs/clients/sdk/AuthApi.java @@ -35,6 +35,7 @@ import io.lakefs.clients.sdk.model.CurrentUser; import io.lakefs.clients.sdk.model.Error; import io.lakefs.clients.sdk.model.ErrorNoACL; +import io.lakefs.clients.sdk.model.ExternalLoginInformation; import io.lakefs.clients.sdk.model.ExternalPrincipal; import io.lakefs.clients.sdk.model.ExternalPrincipalCreation; import io.lakefs.clients.sdk.model.ExternalPrincipalList; @@ -2915,6 +2916,191 @@ public okhttp3.Call executeAsync(final ApiCallback _callback) throws ApiEx public APIdetachPolicyFromUserRequest detachPolicyFromUser(String userId, String policyId) { return new APIdetachPolicyFromUserRequest(userId, policyId); } + private okhttp3.Call externalPrincipalLoginCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (localCustomBaseUrl != null){ + basePath = localCustomBaseUrl; + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[localHostIndex]; + } else { + basePath = null; + } + + Object localVarPostBody = externalLoginInformation; + + // create path and map variables + String localVarPath = "/auth/external/principal/login"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + @SuppressWarnings("rawtypes") + private okhttp3.Call externalPrincipalLoginValidateBeforeCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginCall(externalLoginInformation, _callback); + + } + + + private ApiResponse externalPrincipalLoginWithHttpInfo(ExternalLoginInformation externalLoginInformation) throws ApiException { + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, null); + Type localVarReturnType = new TypeToken(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + } + + private okhttp3.Call externalPrincipalLoginAsync(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, _callback); + Type localVarReturnType = new TypeToken(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback); + return localVarCall; + } + + public class APIexternalPrincipalLoginRequest { + private ExternalLoginInformation externalLoginInformation; + + private APIexternalPrincipalLoginRequest() { + } + + /** + * Set externalLoginInformation + * @param externalLoginInformation (optional) + * @return APIexternalPrincipalLoginRequest + */ + public APIexternalPrincipalLoginRequest externalLoginInformation(ExternalLoginInformation externalLoginInformation) { + this.externalLoginInformation = externalLoginInformation; + return this; + } + + /** + * Build call for externalPrincipalLogin + * @param _callback ApiCallback API callback + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call buildCall(final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginCall(externalLoginInformation, _callback); + } + + /** + * Execute externalPrincipalLogin request + * @return AuthenticationToken + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public AuthenticationToken execute() throws ApiException { + ApiResponse localVarResp = externalPrincipalLoginWithHttpInfo(externalLoginInformation); + return localVarResp.getData(); + } + + /** + * Execute externalPrincipalLogin request with HTTP info returned + * @return ApiResponse<AuthenticationToken> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public ApiResponse executeWithHttpInfo() throws ApiException { + return externalPrincipalLoginWithHttpInfo(externalLoginInformation); + } + + /** + * Execute externalPrincipalLogin request (asynchronously) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call executeAsync(final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginAsync(externalLoginInformation, _callback); + } + } + + /** + * perform a login using an external authenticator + * + * @return APIexternalPrincipalLoginRequest + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public APIexternalPrincipalLoginRequest externalPrincipalLogin() { + return new APIexternalPrincipalLoginRequest(); + } private okhttp3.Call getCredentialsCall(String userId, String accessKeyId, final ApiCallback _callback) throws ApiException { String basePath = null; // Operation Servers diff --git a/clients/java/src/main/java/io/lakefs/clients/sdk/ExperimentalApi.java b/clients/java/src/main/java/io/lakefs/clients/sdk/ExperimentalApi.java index 05975496091..bd2b171ed2c 100644 --- a/clients/java/src/main/java/io/lakefs/clients/sdk/ExperimentalApi.java +++ b/clients/java/src/main/java/io/lakefs/clients/sdk/ExperimentalApi.java @@ -31,6 +31,7 @@ import io.lakefs.clients.sdk.model.AuthenticationToken; import io.lakefs.clients.sdk.model.CompletePresignMultipartUpload; import io.lakefs.clients.sdk.model.Error; +import io.lakefs.clients.sdk.model.ExternalLoginInformation; import io.lakefs.clients.sdk.model.ExternalPrincipal; import io.lakefs.clients.sdk.model.ExternalPrincipalCreation; import io.lakefs.clients.sdk.model.ExternalPrincipalList; @@ -1111,6 +1112,191 @@ public okhttp3.Call executeAsync(final ApiCallback _callback) throws ApiEx public APIdeleteUserExternalPrincipalRequest deleteUserExternalPrincipal(String userId, String principalId) { return new APIdeleteUserExternalPrincipalRequest(userId, principalId); } + private okhttp3.Call externalPrincipalLoginCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (localCustomBaseUrl != null){ + basePath = localCustomBaseUrl; + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[localHostIndex]; + } else { + basePath = null; + } + + Object localVarPostBody = externalLoginInformation; + + // create path and map variables + String localVarPath = "/auth/external/principal/login"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + @SuppressWarnings("rawtypes") + private okhttp3.Call externalPrincipalLoginValidateBeforeCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginCall(externalLoginInformation, _callback); + + } + + + private ApiResponse externalPrincipalLoginWithHttpInfo(ExternalLoginInformation externalLoginInformation) throws ApiException { + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, null); + Type localVarReturnType = new TypeToken(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + } + + private okhttp3.Call externalPrincipalLoginAsync(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, _callback); + Type localVarReturnType = new TypeToken(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback); + return localVarCall; + } + + public class APIexternalPrincipalLoginRequest { + private ExternalLoginInformation externalLoginInformation; + + private APIexternalPrincipalLoginRequest() { + } + + /** + * Set externalLoginInformation + * @param externalLoginInformation (optional) + * @return APIexternalPrincipalLoginRequest + */ + public APIexternalPrincipalLoginRequest externalLoginInformation(ExternalLoginInformation externalLoginInformation) { + this.externalLoginInformation = externalLoginInformation; + return this; + } + + /** + * Build call for externalPrincipalLogin + * @param _callback ApiCallback API callback + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call buildCall(final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginCall(externalLoginInformation, _callback); + } + + /** + * Execute externalPrincipalLogin request + * @return AuthenticationToken + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public AuthenticationToken execute() throws ApiException { + ApiResponse localVarResp = externalPrincipalLoginWithHttpInfo(externalLoginInformation); + return localVarResp.getData(); + } + + /** + * Execute externalPrincipalLogin request with HTTP info returned + * @return ApiResponse<AuthenticationToken> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public ApiResponse executeWithHttpInfo() throws ApiException { + return externalPrincipalLoginWithHttpInfo(externalLoginInformation); + } + + /** + * Execute externalPrincipalLogin request (asynchronously) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call executeAsync(final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginAsync(externalLoginInformation, _callback); + } + } + + /** + * perform a login using an external authenticator + * + * @return APIexternalPrincipalLoginRequest + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public APIexternalPrincipalLoginRequest externalPrincipalLogin() { + return new APIexternalPrincipalLoginRequest(); + } private okhttp3.Call getExternalPrincipalCall(String principalId, final ApiCallback _callback) throws ApiException { String basePath = null; // Operation Servers @@ -1805,6 +1991,7 @@ private APIstsLoginRequest(StsAuthRequest stsAuthRequest) { Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ @@ -1821,6 +2008,7 @@ public okhttp3.Call buildCall(final ApiCallback _callback) throws ApiException { Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ @@ -1838,6 +2026,7 @@ public AuthenticationToken execute() throws ApiException { Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ @@ -1855,6 +2044,7 @@ public ApiResponse executeWithHttpInfo() throws ApiExceptio Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ @@ -1873,6 +2063,7 @@ public okhttp3.Call executeAsync(final ApiCallback _callbac Status Code Description Response Headers 200 successful STS login - 401 Unauthorized - + 420 too many requests - 0 Internal Server Error - */ diff --git a/clients/java/src/main/java/io/lakefs/clients/sdk/ExternalApi.java b/clients/java/src/main/java/io/lakefs/clients/sdk/ExternalApi.java index 9ca35228673..0aa9762e336 100644 --- a/clients/java/src/main/java/io/lakefs/clients/sdk/ExternalApi.java +++ b/clients/java/src/main/java/io/lakefs/clients/sdk/ExternalApi.java @@ -27,7 +27,9 @@ import java.io.IOException; +import io.lakefs.clients.sdk.model.AuthenticationToken; import io.lakefs.clients.sdk.model.Error; +import io.lakefs.clients.sdk.model.ExternalLoginInformation; import io.lakefs.clients.sdk.model.ExternalPrincipal; import io.lakefs.clients.sdk.model.ExternalPrincipalCreation; import io.lakefs.clients.sdk.model.ExternalPrincipalList; @@ -452,6 +454,191 @@ public okhttp3.Call executeAsync(final ApiCallback _callback) throws ApiEx public APIdeleteUserExternalPrincipalRequest deleteUserExternalPrincipal(String userId, String principalId) { return new APIdeleteUserExternalPrincipalRequest(userId, principalId); } + private okhttp3.Call externalPrincipalLoginCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (localCustomBaseUrl != null){ + basePath = localCustomBaseUrl; + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[localHostIndex]; + } else { + basePath = null; + } + + Object localVarPostBody = externalLoginInformation; + + // create path and map variables + String localVarPath = "/auth/external/principal/login"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + @SuppressWarnings("rawtypes") + private okhttp3.Call externalPrincipalLoginValidateBeforeCall(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginCall(externalLoginInformation, _callback); + + } + + + private ApiResponse externalPrincipalLoginWithHttpInfo(ExternalLoginInformation externalLoginInformation) throws ApiException { + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, null); + Type localVarReturnType = new TypeToken(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + } + + private okhttp3.Call externalPrincipalLoginAsync(ExternalLoginInformation externalLoginInformation, final ApiCallback _callback) throws ApiException { + + okhttp3.Call localVarCall = externalPrincipalLoginValidateBeforeCall(externalLoginInformation, _callback); + Type localVarReturnType = new TypeToken(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback); + return localVarCall; + } + + public class APIexternalPrincipalLoginRequest { + private ExternalLoginInformation externalLoginInformation; + + private APIexternalPrincipalLoginRequest() { + } + + /** + * Set externalLoginInformation + * @param externalLoginInformation (optional) + * @return APIexternalPrincipalLoginRequest + */ + public APIexternalPrincipalLoginRequest externalLoginInformation(ExternalLoginInformation externalLoginInformation) { + this.externalLoginInformation = externalLoginInformation; + return this; + } + + /** + * Build call for externalPrincipalLogin + * @param _callback ApiCallback API callback + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call buildCall(final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginCall(externalLoginInformation, _callback); + } + + /** + * Execute externalPrincipalLogin request + * @return AuthenticationToken + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public AuthenticationToken execute() throws ApiException { + ApiResponse localVarResp = externalPrincipalLoginWithHttpInfo(externalLoginInformation); + return localVarResp.getData(); + } + + /** + * Execute externalPrincipalLogin request with HTTP info returned + * @return ApiResponse<AuthenticationToken> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public ApiResponse executeWithHttpInfo() throws ApiException { + return externalPrincipalLoginWithHttpInfo(externalLoginInformation); + } + + /** + * Execute externalPrincipalLogin request (asynchronously) + * @param _callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public okhttp3.Call executeAsync(final ApiCallback _callback) throws ApiException { + return externalPrincipalLoginAsync(externalLoginInformation, _callback); + } + } + + /** + * perform a login using an external authenticator + * + * @return APIexternalPrincipalLoginRequest + * @http.response.details + + + + + + + + + +
Status Code Description Response Headers
200 successful external login -
400 Bad Request -
401 Unauthorized -
403 Forbidden -
404 Resource Not Found -
420 too many requests -
0 Internal Server Error -
+ */ + public APIexternalPrincipalLoginRequest externalPrincipalLogin() { + return new APIexternalPrincipalLoginRequest(); + } private okhttp3.Call getExternalPrincipalCall(String principalId, final ApiCallback _callback) throws ApiException { String basePath = null; // Operation Servers diff --git a/clients/java/src/main/java/io/lakefs/clients/sdk/JSON.java b/clients/java/src/main/java/io/lakefs/clients/sdk/JSON.java index 7203a5c5512..c1b6c618cc5 100644 --- a/clients/java/src/main/java/io/lakefs/clients/sdk/JSON.java +++ b/clients/java/src/main/java/io/lakefs/clients/sdk/JSON.java @@ -118,6 +118,7 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri gsonBuilder.registerTypeAdapterFactory(new io.lakefs.clients.sdk.model.DiffList.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new io.lakefs.clients.sdk.model.Error.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new io.lakefs.clients.sdk.model.ErrorNoACL.CustomTypeAdapterFactory()); + gsonBuilder.registerTypeAdapterFactory(new io.lakefs.clients.sdk.model.ExternalLoginInformation.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new io.lakefs.clients.sdk.model.ExternalPrincipal.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new io.lakefs.clients.sdk.model.ExternalPrincipalCreation.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new io.lakefs.clients.sdk.model.ExternalPrincipalList.CustomTypeAdapterFactory()); diff --git a/clients/java/src/main/java/io/lakefs/clients/sdk/model/ExternalLoginInformation.java b/clients/java/src/main/java/io/lakefs/clients/sdk/model/ExternalLoginInformation.java new file mode 100644 index 00000000000..ae63343c140 --- /dev/null +++ b/clients/java/src/main/java/io/lakefs/clients/sdk/model/ExternalLoginInformation.java @@ -0,0 +1,318 @@ +/* + * lakeFS API + * lakeFS HTTP API + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package io.lakefs.clients.sdk.model; + +import java.util.Objects; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.Arrays; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import io.lakefs.clients.sdk.JSON; + +/** + * ExternalLoginInformation + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class ExternalLoginInformation { + public static final String SERIALIZED_NAME_TOKEN_EXPIRATION_DURATION = "token_expiration_duration"; + @SerializedName(SERIALIZED_NAME_TOKEN_EXPIRATION_DURATION) + private Integer tokenExpirationDuration; + + public static final String SERIALIZED_NAME_IDENTITY_REQUEST = "identityRequest"; + @SerializedName(SERIALIZED_NAME_IDENTITY_REQUEST) + private Object identityRequest; + + public ExternalLoginInformation() { + } + + public ExternalLoginInformation tokenExpirationDuration(Integer tokenExpirationDuration) { + + this.tokenExpirationDuration = tokenExpirationDuration; + return this; + } + + /** + * Get tokenExpirationDuration + * @return tokenExpirationDuration + **/ + @javax.annotation.Nullable + public Integer getTokenExpirationDuration() { + return tokenExpirationDuration; + } + + + public void setTokenExpirationDuration(Integer tokenExpirationDuration) { + this.tokenExpirationDuration = tokenExpirationDuration; + } + + + public ExternalLoginInformation identityRequest(Object identityRequest) { + + this.identityRequest = identityRequest; + return this; + } + + /** + * Get identityRequest + * @return identityRequest + **/ + @javax.annotation.Nonnull + public Object getIdentityRequest() { + return identityRequest; + } + + + public void setIdentityRequest(Object identityRequest) { + this.identityRequest = identityRequest; + } + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + * + * @param key name of the property + * @param value value of the property + * @return the ExternalLoginInformation instance itself + */ + public ExternalLoginInformation putAdditionalProperty(String key, Object value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + * + * @return a map of objects + */ + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + * + * @param key name of the property + * @return an object + */ + public Object getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ExternalLoginInformation externalLoginInformation = (ExternalLoginInformation) o; + return Objects.equals(this.tokenExpirationDuration, externalLoginInformation.tokenExpirationDuration) && + Objects.equals(this.identityRequest, externalLoginInformation.identityRequest)&& + Objects.equals(this.additionalProperties, externalLoginInformation.additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(tokenExpirationDuration, identityRequest, additionalProperties); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ExternalLoginInformation {\n"); + sb.append(" tokenExpirationDuration: ").append(toIndentedString(tokenExpirationDuration)).append("\n"); + sb.append(" identityRequest: ").append(toIndentedString(identityRequest)).append("\n"); + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + + public static HashSet openapiFields; + public static HashSet openapiRequiredFields; + + static { + // a set of all properties/fields (JSON key names) + openapiFields = new HashSet(); + openapiFields.add("token_expiration_duration"); + openapiFields.add("identityRequest"); + + // a set of required properties/fields (JSON key names) + openapiRequiredFields = new HashSet(); + openapiRequiredFields.add("identityRequest"); + } + + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to ExternalLoginInformation + */ + public static void validateJsonElement(JsonElement jsonElement) throws IOException { + if (jsonElement == null) { + if (!ExternalLoginInformation.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null + throw new IllegalArgumentException(String.format("The required field(s) %s in ExternalLoginInformation is not found in the empty JSON string", ExternalLoginInformation.openapiRequiredFields.toString())); + } + } + + // check to make sure all required properties/fields are present in the JSON string + for (String requiredField : ExternalLoginInformation.openapiRequiredFields) { + if (jsonElement.getAsJsonObject().get(requiredField) == null) { + throw new IllegalArgumentException(String.format("The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString())); + } + } + JsonObject jsonObj = jsonElement.getAsJsonObject(); + } + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!ExternalLoginInformation.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes 'ExternalLoginInformation' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + final TypeAdapter thisAdapter + = gson.getDelegateAdapter(this, TypeToken.get(ExternalLoginInformation.class)); + + return (TypeAdapter) new TypeAdapter() { + @Override + public void write(JsonWriter out, ExternalLoginInformation value) throws IOException { + JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); + obj.remove("additionalProperties"); + // serialize additional properties + if (value.getAdditionalProperties() != null) { + for (Map.Entry entry : value.getAdditionalProperties().entrySet()) { + if (entry.getValue() instanceof String) + obj.addProperty(entry.getKey(), (String) entry.getValue()); + else if (entry.getValue() instanceof Number) + obj.addProperty(entry.getKey(), (Number) entry.getValue()); + else if (entry.getValue() instanceof Boolean) + obj.addProperty(entry.getKey(), (Boolean) entry.getValue()); + else if (entry.getValue() instanceof Character) + obj.addProperty(entry.getKey(), (Character) entry.getValue()); + else { + obj.add(entry.getKey(), gson.toJsonTree(entry.getValue()).getAsJsonObject()); + } + } + } + elementAdapter.write(out, obj); + } + + @Override + public ExternalLoginInformation read(JsonReader in) throws IOException { + JsonElement jsonElement = elementAdapter.read(in); + validateJsonElement(jsonElement); + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // store additional fields in the deserialized instance + ExternalLoginInformation instance = thisAdapter.fromJsonTree(jsonObj); + for (Map.Entry entry : jsonObj.entrySet()) { + if (!openapiFields.contains(entry.getKey())) { + if (entry.getValue().isJsonPrimitive()) { // primitive type + if (entry.getValue().getAsJsonPrimitive().isString()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString()); + else if (entry.getValue().getAsJsonPrimitive().isNumber()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber()); + else if (entry.getValue().getAsJsonPrimitive().isBoolean()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean()); + else + throw new IllegalArgumentException(String.format("The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString())); + } else if (entry.getValue().isJsonArray()) { + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class)); + } else { // JSON object + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class)); + } + } + } + return instance; + } + + }.nullSafe(); + } + } + + /** + * Create an instance of ExternalLoginInformation given an JSON string + * + * @param jsonString JSON string + * @return An instance of ExternalLoginInformation + * @throws IOException if the JSON string is invalid with respect to ExternalLoginInformation + */ + public static ExternalLoginInformation fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, ExternalLoginInformation.class); + } + + /** + * Convert an instance of ExternalLoginInformation to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} + diff --git a/clients/java/src/main/java/io/lakefs/clients/sdk/model/StsAuthRequest.java b/clients/java/src/main/java/io/lakefs/clients/sdk/model/StsAuthRequest.java index 5d6bd245e2c..b3e67353f7d 100644 --- a/clients/java/src/main/java/io/lakefs/clients/sdk/model/StsAuthRequest.java +++ b/clients/java/src/main/java/io/lakefs/clients/sdk/model/StsAuthRequest.java @@ -141,7 +141,7 @@ public StsAuthRequest ttlSeconds(Long ttlSeconds) { } /** - * The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. + * The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. * @return ttlSeconds **/ @javax.annotation.Nullable diff --git a/clients/java/src/test/java/io/lakefs/clients/sdk/AuthApiTest.java b/clients/java/src/test/java/io/lakefs/clients/sdk/AuthApiTest.java index f9d84601df9..0e1114c79fc 100644 --- a/clients/java/src/test/java/io/lakefs/clients/sdk/AuthApiTest.java +++ b/clients/java/src/test/java/io/lakefs/clients/sdk/AuthApiTest.java @@ -22,6 +22,7 @@ import io.lakefs.clients.sdk.model.CurrentUser; import io.lakefs.clients.sdk.model.Error; import io.lakefs.clients.sdk.model.ErrorNoACL; +import io.lakefs.clients.sdk.model.ExternalLoginInformation; import io.lakefs.clients.sdk.model.ExternalPrincipal; import io.lakefs.clients.sdk.model.ExternalPrincipalCreation; import io.lakefs.clients.sdk.model.ExternalPrincipalList; @@ -271,6 +272,20 @@ public void detachPolicyFromUserTest() throws ApiException { // TODO: test validations } + /** + * perform a login using an external authenticator + * + * @throws ApiException if the Api call fails + */ + @Test + public void externalPrincipalLoginTest() throws ApiException { + ExternalLoginInformation externalLoginInformation = null; + AuthenticationToken response = api.externalPrincipalLogin() + .externalLoginInformation(externalLoginInformation) + .execute(); + // TODO: test validations + } + /** * get credentials * diff --git a/clients/java/src/test/java/io/lakefs/clients/sdk/ExperimentalApiTest.java b/clients/java/src/test/java/io/lakefs/clients/sdk/ExperimentalApiTest.java index 5f95e34cc4d..98cc07acb4b 100644 --- a/clients/java/src/test/java/io/lakefs/clients/sdk/ExperimentalApiTest.java +++ b/clients/java/src/test/java/io/lakefs/clients/sdk/ExperimentalApiTest.java @@ -18,6 +18,7 @@ import io.lakefs.clients.sdk.model.AuthenticationToken; import io.lakefs.clients.sdk.model.CompletePresignMultipartUpload; import io.lakefs.clients.sdk.model.Error; +import io.lakefs.clients.sdk.model.ExternalLoginInformation; import io.lakefs.clients.sdk.model.ExternalPrincipal; import io.lakefs.clients.sdk.model.ExternalPrincipalCreation; import io.lakefs.clients.sdk.model.ExternalPrincipalList; @@ -130,6 +131,20 @@ public void deleteUserExternalPrincipalTest() throws ApiException { // TODO: test validations } + /** + * perform a login using an external authenticator + * + * @throws ApiException if the Api call fails + */ + @Test + public void externalPrincipalLoginTest() throws ApiException { + ExternalLoginInformation externalLoginInformation = null; + AuthenticationToken response = api.externalPrincipalLogin() + .externalLoginInformation(externalLoginInformation) + .execute(); + // TODO: test validations + } + /** * describe external principal by id * diff --git a/clients/java/src/test/java/io/lakefs/clients/sdk/ExternalApiTest.java b/clients/java/src/test/java/io/lakefs/clients/sdk/ExternalApiTest.java index 602fc8a898b..3dd32421e88 100644 --- a/clients/java/src/test/java/io/lakefs/clients/sdk/ExternalApiTest.java +++ b/clients/java/src/test/java/io/lakefs/clients/sdk/ExternalApiTest.java @@ -14,7 +14,9 @@ package io.lakefs.clients.sdk; import io.lakefs.clients.sdk.ApiException; +import io.lakefs.clients.sdk.model.AuthenticationToken; import io.lakefs.clients.sdk.model.Error; +import io.lakefs.clients.sdk.model.ExternalLoginInformation; import io.lakefs.clients.sdk.model.ExternalPrincipal; import io.lakefs.clients.sdk.model.ExternalPrincipalCreation; import io.lakefs.clients.sdk.model.ExternalPrincipalList; @@ -64,6 +66,20 @@ public void deleteUserExternalPrincipalTest() throws ApiException { // TODO: test validations } + /** + * perform a login using an external authenticator + * + * @throws ApiException if the Api call fails + */ + @Test + public void externalPrincipalLoginTest() throws ApiException { + ExternalLoginInformation externalLoginInformation = null; + AuthenticationToken response = api.externalPrincipalLogin() + .externalLoginInformation(externalLoginInformation) + .execute(); + // TODO: test validations + } + /** * describe external principal by id * diff --git a/clients/java/src/test/java/io/lakefs/clients/sdk/model/ExternalLoginInformationTest.java b/clients/java/src/test/java/io/lakefs/clients/sdk/model/ExternalLoginInformationTest.java new file mode 100644 index 00000000000..962495b581f --- /dev/null +++ b/clients/java/src/test/java/io/lakefs/clients/sdk/model/ExternalLoginInformationTest.java @@ -0,0 +1,56 @@ +/* + * lakeFS API + * lakeFS HTTP API + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package io.lakefs.clients.sdk.model; + +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.Arrays; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +/** + * Model tests for ExternalLoginInformation + */ +public class ExternalLoginInformationTest { + private final ExternalLoginInformation model = new ExternalLoginInformation(); + + /** + * Model tests for ExternalLoginInformation + */ + @Test + public void testExternalLoginInformation() { + // TODO: test ExternalLoginInformation + } + + /** + * Test the property 'tokenExpirationDuration' + */ + @Test + public void tokenExpirationDurationTest() { + // TODO: test tokenExpirationDuration + } + + /** + * Test the property 'identityRequest' + */ + @Test + public void identityRequestTest() { + // TODO: test identityRequest + } + +} diff --git a/clients/python-legacy/.openapi-generator/FILES b/clients/python-legacy/.openapi-generator/FILES index 5930127d4a9..091104d1590 100644 --- a/clients/python-legacy/.openapi-generator/FILES +++ b/clients/python-legacy/.openapi-generator/FILES @@ -34,6 +34,7 @@ docs/Error.md docs/ErrorNoACL.md docs/ExperimentalApi.md docs/ExternalApi.md +docs/ExternalLoginInformation.md docs/ExternalPrincipal.md docs/ExternalPrincipalCreation.md docs/ExternalPrincipalList.md @@ -169,6 +170,7 @@ lakefs_client/model/diff.py lakefs_client/model/diff_list.py lakefs_client/model/error.py lakefs_client/model/error_no_acl.py +lakefs_client/model/external_login_information.py lakefs_client/model/external_principal.py lakefs_client/model/external_principal_creation.py lakefs_client/model/external_principal_list.py @@ -285,6 +287,7 @@ test/test_error.py test/test_error_no_acl.py test/test_experimental_api.py test/test_external_api.py +test/test_external_login_information.py test/test_external_principal.py test/test_external_principal_creation.py test/test_external_principal_list.py diff --git a/clients/python-legacy/README.md b/clients/python-legacy/README.md index 844fa24d27b..362b8560ef9 100644 --- a/clients/python-legacy/README.md +++ b/clients/python-legacy/README.md @@ -136,6 +136,7 @@ Class | Method | HTTP request | Description *AuthApi* | [**delete_user_external_principal**](docs/AuthApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user *AuthApi* | [**detach_policy_from_group**](docs/AuthApi.md#detach_policy_from_group) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group *AuthApi* | [**detach_policy_from_user**](docs/AuthApi.md#detach_policy_from_user) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user +*AuthApi* | [**external_principal_login**](docs/AuthApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator *AuthApi* | [**get_credentials**](docs/AuthApi.md#get_credentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials *AuthApi* | [**get_current_user**](docs/AuthApi.md#get_current_user) | **GET** /user | get current user *AuthApi* | [**get_external_principal**](docs/AuthApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id @@ -171,12 +172,14 @@ Class | Method | HTTP request | Description *ExperimentalApi* | [**create_presign_multipart_upload**](docs/ExperimentalApi.md#create_presign_multipart_upload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload *ExperimentalApi* | [**create_user_external_principal**](docs/ExperimentalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExperimentalApi* | [**delete_user_external_principal**](docs/ExperimentalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExperimentalApi* | [**external_principal_login**](docs/ExperimentalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExperimentalApi* | [**get_external_principal**](docs/ExperimentalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id *ExperimentalApi* | [**hard_reset_branch**](docs/ExperimentalApi.md#hard_reset_branch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch *ExperimentalApi* | [**list_user_external_principals**](docs/ExperimentalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *ExperimentalApi* | [**sts_login**](docs/ExperimentalApi.md#sts_login) | **POST** /sts/login | perform a login with STS *ExternalApi* | [**create_user_external_principal**](docs/ExternalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExternalApi* | [**delete_user_external_principal**](docs/ExternalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExternalApi* | [**external_principal_login**](docs/ExternalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExternalApi* | [**get_external_principal**](docs/ExternalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id *ExternalApi* | [**list_user_external_principals**](docs/ExternalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *HealthCheckApi* | [**health_check**](docs/HealthCheckApi.md#health_check) | **GET** /healthcheck | @@ -274,6 +277,7 @@ Class | Method | HTTP request | Description - [DiffList](docs/DiffList.md) - [Error](docs/Error.md) - [ErrorNoACL](docs/ErrorNoACL.md) + - [ExternalLoginInformation](docs/ExternalLoginInformation.md) - [ExternalPrincipal](docs/ExternalPrincipal.md) - [ExternalPrincipalCreation](docs/ExternalPrincipalCreation.md) - [ExternalPrincipalList](docs/ExternalPrincipalList.md) diff --git a/clients/python-legacy/docs/AuthApi.md b/clients/python-legacy/docs/AuthApi.md index d80931429c1..c73a1b73998 100644 --- a/clients/python-legacy/docs/AuthApi.md +++ b/clients/python-legacy/docs/AuthApi.md @@ -20,6 +20,7 @@ Method | HTTP request | Description [**delete_user_external_principal**](AuthApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user [**detach_policy_from_group**](AuthApi.md#detach_policy_from_group) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group [**detach_policy_from_user**](AuthApi.md#detach_policy_from_user) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user +[**external_principal_login**](AuthApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**get_credentials**](AuthApi.md#get_credentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials [**get_current_user**](AuthApi.md#get_current_user) | **GET** /user | get current user [**get_external_principal**](AuthApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id @@ -1804,6 +1805,83 @@ void (empty response body) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **external_principal_login** +> AuthenticationToken external_principal_login() + +perform a login using an external authenticator + +### Example + + +```python +import time +import lakefs_client +from lakefs_client.api import auth_api +from lakefs_client.model.authentication_token import AuthenticationToken +from lakefs_client.model.external_login_information import ExternalLoginInformation +from lakefs_client.model.error import Error +from pprint import pprint +# Defining the host is optional and defaults to http://localhost/api/v1 +# See configuration.py for a list of all supported configuration parameters. +configuration = lakefs_client.Configuration( + host = "http://localhost/api/v1" +) + + +# Enter a context with an instance of the API client +with lakefs_client.ApiClient() as api_client: + # Create an instance of the API class + api_instance = auth_api.AuthApi(api_client) + external_login_information = ExternalLoginInformation( + token_expiration_duration=1, + identity_request={}, + ) # ExternalLoginInformation | (optional) + + # example passing only required values which don't have defaults set + # and optional values + try: + # perform a login using an external authenticator + api_response = api_instance.external_principal_login(external_login_information=external_login_information) + pprint(api_response) + except lakefs_client.ApiException as e: + print("Exception when calling AuthApi->external_principal_login: %s\n" % e) +``` + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **external_login_information** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **get_credentials** > Credentials get_credentials(user_id, access_key_id) diff --git a/clients/python-legacy/docs/ExperimentalApi.md b/clients/python-legacy/docs/ExperimentalApi.md index 4f24b30f6e0..240343328b3 100644 --- a/clients/python-legacy/docs/ExperimentalApi.md +++ b/clients/python-legacy/docs/ExperimentalApi.md @@ -9,6 +9,7 @@ Method | HTTP request | Description [**create_presign_multipart_upload**](ExperimentalApi.md#create_presign_multipart_upload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload [**create_user_external_principal**](ExperimentalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user [**delete_user_external_principal**](ExperimentalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +[**external_principal_login**](ExperimentalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**get_external_principal**](ExperimentalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id [**hard_reset_branch**](ExperimentalApi.md#hard_reset_branch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch [**list_user_external_principals**](ExperimentalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user @@ -646,6 +647,83 @@ void (empty response body) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **external_principal_login** +> AuthenticationToken external_principal_login() + +perform a login using an external authenticator + +### Example + + +```python +import time +import lakefs_client +from lakefs_client.api import experimental_api +from lakefs_client.model.authentication_token import AuthenticationToken +from lakefs_client.model.external_login_information import ExternalLoginInformation +from lakefs_client.model.error import Error +from pprint import pprint +# Defining the host is optional and defaults to http://localhost/api/v1 +# See configuration.py for a list of all supported configuration parameters. +configuration = lakefs_client.Configuration( + host = "http://localhost/api/v1" +) + + +# Enter a context with an instance of the API client +with lakefs_client.ApiClient() as api_client: + # Create an instance of the API class + api_instance = experimental_api.ExperimentalApi(api_client) + external_login_information = ExternalLoginInformation( + token_expiration_duration=1, + identity_request={}, + ) # ExternalLoginInformation | (optional) + + # example passing only required values which don't have defaults set + # and optional values + try: + # perform a login using an external authenticator + api_response = api_instance.external_principal_login(external_login_information=external_login_information) + pprint(api_response) + except lakefs_client.ApiException as e: + print("Exception when calling ExperimentalApi->external_principal_login: %s\n" % e) +``` + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **external_login_information** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **get_external_principal** > ExternalPrincipal get_external_principal(principal_id) @@ -1071,6 +1149,7 @@ No authorization required |-------------|-------------|------------------| **200** | successful STS login | - | **401** | Unauthorized | - | +**420** | too many requests | - | **0** | Internal Server Error | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/clients/python-legacy/docs/ExternalApi.md b/clients/python-legacy/docs/ExternalApi.md index 2f213f74f0e..761f96d6897 100644 --- a/clients/python-legacy/docs/ExternalApi.md +++ b/clients/python-legacy/docs/ExternalApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**create_user_external_principal**](ExternalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user [**delete_user_external_principal**](ExternalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +[**external_principal_login**](ExternalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**get_external_principal**](ExternalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id [**list_user_external_principals**](ExternalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user @@ -244,6 +245,83 @@ void (empty response body) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **external_principal_login** +> AuthenticationToken external_principal_login() + +perform a login using an external authenticator + +### Example + + +```python +import time +import lakefs_client +from lakefs_client.api import external_api +from lakefs_client.model.authentication_token import AuthenticationToken +from lakefs_client.model.external_login_information import ExternalLoginInformation +from lakefs_client.model.error import Error +from pprint import pprint +# Defining the host is optional and defaults to http://localhost/api/v1 +# See configuration.py for a list of all supported configuration parameters. +configuration = lakefs_client.Configuration( + host = "http://localhost/api/v1" +) + + +# Enter a context with an instance of the API client +with lakefs_client.ApiClient() as api_client: + # Create an instance of the API class + api_instance = external_api.ExternalApi(api_client) + external_login_information = ExternalLoginInformation( + token_expiration_duration=1, + identity_request={}, + ) # ExternalLoginInformation | (optional) + + # example passing only required values which don't have defaults set + # and optional values + try: + # perform a login using an external authenticator + api_response = api_instance.external_principal_login(external_login_information=external_login_information) + pprint(api_response) + except lakefs_client.ApiException as e: + print("Exception when calling ExternalApi->external_principal_login: %s\n" % e) +``` + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **external_login_information** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **get_external_principal** > ExternalPrincipal get_external_principal(principal_id) diff --git a/clients/python-legacy/docs/ExternalLoginInformation.md b/clients/python-legacy/docs/ExternalLoginInformation.md new file mode 100644 index 00000000000..26410a639de --- /dev/null +++ b/clients/python-legacy/docs/ExternalLoginInformation.md @@ -0,0 +1,13 @@ +# ExternalLoginInformation + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**identity_request** | **{str: (bool, date, datetime, dict, float, int, list, str, none_type)}** | | +**token_expiration_duration** | **int** | | [optional] +**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/clients/python-legacy/docs/StsAuthRequest.md b/clients/python-legacy/docs/StsAuthRequest.md index c21cd844ee1..3ed7faaa7a9 100644 --- a/clients/python-legacy/docs/StsAuthRequest.md +++ b/clients/python-legacy/docs/StsAuthRequest.md @@ -7,7 +7,7 @@ Name | Type | Description | Notes **code** | **str** | | **state** | **str** | | **redirect_uri** | **str** | | -**ttl_seconds** | **int** | The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. | [optional] +**ttl_seconds** | **int** | The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. | [optional] **any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/clients/python-legacy/lakefs_client/api/auth_api.py b/clients/python-legacy/lakefs_client/api/auth_api.py index 62d7e032a2f..81990d1319f 100644 --- a/clients/python-legacy/lakefs_client/api/auth_api.py +++ b/clients/python-legacy/lakefs_client/api/auth_api.py @@ -30,6 +30,7 @@ from lakefs_client.model.current_user import CurrentUser from lakefs_client.model.error import Error from lakefs_client.model.error_no_acl import ErrorNoACL +from lakefs_client.model.external_login_information import ExternalLoginInformation from lakefs_client.model.external_principal import ExternalPrincipal from lakefs_client.model.external_principal_creation import ExternalPrincipalCreation from lakefs_client.model.external_principal_list import ExternalPrincipalList @@ -994,6 +995,54 @@ def __init__(self, api_client=None): }, api_client=api_client ) + self.external_principal_login_endpoint = _Endpoint( + settings={ + 'response_type': (AuthenticationToken,), + 'auth': [], + 'endpoint_path': '/auth/external/principal/login', + 'operation_id': 'external_principal_login', + 'http_method': 'POST', + 'servers': None, + }, + params_map={ + 'all': [ + 'external_login_information', + ], + 'required': [], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'external_login_information': + (ExternalLoginInformation,), + }, + 'attribute_map': { + }, + 'location_map': { + 'external_login_information': 'body', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [ + 'application/json' + ] + }, + api_client=api_client + ) self.get_credentials_endpoint = _Endpoint( settings={ 'response_type': (Credentials,), @@ -3288,6 +3337,67 @@ def detach_policy_from_user( policy_id return self.detach_policy_from_user_endpoint.call_with_http_info(**kwargs) + def external_principal_login( + self, + **kwargs + ): + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login(async_req=True) + >>> result = thread.get() + + + Keyword Args: + external_login_information (ExternalLoginInformation): [optional] + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (int/float/tuple): timeout setting for this request. If + one number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously + + Returns: + AuthenticationToken + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_host_index'] = kwargs.get('_host_index') + return self.external_principal_login_endpoint.call_with_http_info(**kwargs) + def get_credentials( self, user_id, diff --git a/clients/python-legacy/lakefs_client/api/experimental_api.py b/clients/python-legacy/lakefs_client/api/experimental_api.py index 2a1131527d8..0b30ed08bc4 100644 --- a/clients/python-legacy/lakefs_client/api/experimental_api.py +++ b/clients/python-legacy/lakefs_client/api/experimental_api.py @@ -26,6 +26,7 @@ from lakefs_client.model.authentication_token import AuthenticationToken from lakefs_client.model.complete_presign_multipart_upload import CompletePresignMultipartUpload from lakefs_client.model.error import Error +from lakefs_client.model.external_login_information import ExternalLoginInformation from lakefs_client.model.external_principal import ExternalPrincipal from lakefs_client.model.external_principal_creation import ExternalPrincipalCreation from lakefs_client.model.external_principal_list import ExternalPrincipalList @@ -404,6 +405,54 @@ def __init__(self, api_client=None): }, api_client=api_client ) + self.external_principal_login_endpoint = _Endpoint( + settings={ + 'response_type': (AuthenticationToken,), + 'auth': [], + 'endpoint_path': '/auth/external/principal/login', + 'operation_id': 'external_principal_login', + 'http_method': 'POST', + 'servers': None, + }, + params_map={ + 'all': [ + 'external_login_information', + ], + 'required': [], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'external_login_information': + (ExternalLoginInformation,), + }, + 'attribute_map': { + }, + 'location_map': { + 'external_login_information': 'body', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [ + 'application/json' + ] + }, + api_client=api_client + ) self.get_external_principal_endpoint = _Endpoint( settings={ 'response_type': (ExternalPrincipal,), @@ -1030,6 +1079,67 @@ def delete_user_external_principal( principal_id return self.delete_user_external_principal_endpoint.call_with_http_info(**kwargs) + def external_principal_login( + self, + **kwargs + ): + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login(async_req=True) + >>> result = thread.get() + + + Keyword Args: + external_login_information (ExternalLoginInformation): [optional] + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (int/float/tuple): timeout setting for this request. If + one number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously + + Returns: + AuthenticationToken + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_host_index'] = kwargs.get('_host_index') + return self.external_principal_login_endpoint.call_with_http_info(**kwargs) + def get_external_principal( self, principal_id, diff --git a/clients/python-legacy/lakefs_client/api/external_api.py b/clients/python-legacy/lakefs_client/api/external_api.py index 692f2b0fc30..fe4328a3570 100644 --- a/clients/python-legacy/lakefs_client/api/external_api.py +++ b/clients/python-legacy/lakefs_client/api/external_api.py @@ -22,7 +22,9 @@ none_type, validate_and_convert_types ) +from lakefs_client.model.authentication_token import AuthenticationToken from lakefs_client.model.error import Error +from lakefs_client.model.external_login_information import ExternalLoginInformation from lakefs_client.model.external_principal import ExternalPrincipal from lakefs_client.model.external_principal_creation import ExternalPrincipalCreation from lakefs_client.model.external_principal_list import ExternalPrincipalList @@ -167,6 +169,54 @@ def __init__(self, api_client=None): }, api_client=api_client ) + self.external_principal_login_endpoint = _Endpoint( + settings={ + 'response_type': (AuthenticationToken,), + 'auth': [], + 'endpoint_path': '/auth/external/principal/login', + 'operation_id': 'external_principal_login', + 'http_method': 'POST', + 'servers': None, + }, + params_map={ + 'all': [ + 'external_login_information', + ], + 'required': [], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'external_login_information': + (ExternalLoginInformation,), + }, + 'attribute_map': { + }, + 'location_map': { + 'external_login_information': 'body', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [ + 'application/json' + ] + }, + api_client=api_client + ) self.get_external_principal_endpoint = _Endpoint( settings={ 'response_type': (ExternalPrincipal,), @@ -438,6 +488,67 @@ def delete_user_external_principal( principal_id return self.delete_user_external_principal_endpoint.call_with_http_info(**kwargs) + def external_principal_login( + self, + **kwargs + ): + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login(async_req=True) + >>> result = thread.get() + + + Keyword Args: + external_login_information (ExternalLoginInformation): [optional] + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (int/float/tuple): timeout setting for this request. If + one number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously + + Returns: + AuthenticationToken + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_host_index'] = kwargs.get('_host_index') + return self.external_principal_login_endpoint.call_with_http_info(**kwargs) + def get_external_principal( self, principal_id, diff --git a/clients/python-legacy/lakefs_client/model/external_login_information.py b/clients/python-legacy/lakefs_client/model/external_login_information.py new file mode 100644 index 00000000000..4c4e3cea5a5 --- /dev/null +++ b/clients/python-legacy/lakefs_client/model/external_login_information.py @@ -0,0 +1,266 @@ +""" + lakeFS API + + lakeFS HTTP API # noqa: E501 + + The version of the OpenAPI document: 1.0.0 + Contact: services@treeverse.io + Generated by: https://openapi-generator.tech +""" + + +import re # noqa: F401 +import sys # noqa: F401 + +from lakefs_client.model_utils import ( # noqa: F401 + ApiTypeError, + ModelComposed, + ModelNormal, + ModelSimple, + cached_property, + change_keys_js_to_python, + convert_js_args_to_python_args, + date, + datetime, + file_type, + none_type, + validate_get_composed_info, +) +from ..model_utils import OpenApiModel +from lakefs_client.exceptions import ApiAttributeError + + + +class ExternalLoginInformation(ModelNormal): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: + allowed_values (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + with a capitalized key describing the allowed value and an allowed + value. These dicts store the allowed enum values. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + discriminator_value_class_map (dict): A dict to go from the discriminator + variable value to the discriminator class name. + validations (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + that stores validations for max_length, min_length, max_items, + min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum, + inclusive_minimum, and regex. + additional_properties_type (tuple): A tuple of classes accepted + as additional properties values. + """ + + allowed_values = { + } + + validations = { + } + + @cached_property + def additional_properties_type(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + """ + return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501 + + _nullable = False + + @cached_property + def openapi_types(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + + Returns + openapi_types (dict): The key is attribute name + and the value is attribute type. + """ + return { + 'identity_request': ({str: (bool, date, datetime, dict, float, int, list, str, none_type)},), # noqa: E501 + 'token_expiration_duration': (int,), # noqa: E501 + } + + @cached_property + def discriminator(): + return None + + + attribute_map = { + 'identity_request': 'identityRequest', # noqa: E501 + 'token_expiration_duration': 'token_expiration_duration', # noqa: E501 + } + + read_only_vars = { + } + + _composed_schemas = {} + + @classmethod + @convert_js_args_to_python_args + def _from_openapi_data(cls, identity_request, *args, **kwargs): # noqa: E501 + """ExternalLoginInformation - a model defined in OpenAPI + + Args: + identity_request ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + token_expiration_duration (int): [optional] # noqa: E501 + """ + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + self = super(OpenApiModel, cls).__new__(cls) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + self.identity_request = identity_request + for var_name, var_value in kwargs.items(): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue + setattr(self, var_name, var_value) + return self + + required_properties = set([ + '_data_store', + '_check_type', + '_spec_property_naming', + '_path_to_item', + '_configuration', + '_visited_composed_classes', + ]) + + @convert_js_args_to_python_args + def __init__(self, identity_request, *args, **kwargs): # noqa: E501 + """ExternalLoginInformation - a model defined in OpenAPI + + Args: + identity_request ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + token_expiration_duration (int): [optional] # noqa: E501 + """ + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + self.identity_request = identity_request + for var_name, var_value in kwargs.items(): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue + setattr(self, var_name, var_value) + if var_name in self.read_only_vars: + raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate " + f"class with read only attributes.") diff --git a/clients/python-legacy/lakefs_client/model/sts_auth_request.py b/clients/python-legacy/lakefs_client/model/sts_auth_request.py index 6cea53cffc8..fde8b5f19dd 100644 --- a/clients/python-legacy/lakefs_client/model/sts_auth_request.py +++ b/clients/python-legacy/lakefs_client/model/sts_auth_request.py @@ -146,7 +146,7 @@ def _from_openapi_data(cls, code, state, redirect_uri, *args, **kwargs): # noqa Animal class but this time we won't travel through its discriminator because we passed in _visited_composed_classes = (Animal,) - ttl_seconds (int): The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. . [optional] # noqa: E501 + ttl_seconds (int): The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. . [optional] # noqa: E501 """ _check_type = kwargs.pop('_check_type', True) @@ -236,7 +236,7 @@ def __init__(self, code, state, redirect_uri, *args, **kwargs): # noqa: E501 Animal class but this time we won't travel through its discriminator because we passed in _visited_composed_classes = (Animal,) - ttl_seconds (int): The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. . [optional] # noqa: E501 + ttl_seconds (int): The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. . [optional] # noqa: E501 """ _check_type = kwargs.pop('_check_type', True) diff --git a/clients/python-legacy/lakefs_client/models/__init__.py b/clients/python-legacy/lakefs_client/models/__init__.py index ab42d92747f..a042d843e8b 100644 --- a/clients/python-legacy/lakefs_client/models/__init__.py +++ b/clients/python-legacy/lakefs_client/models/__init__.py @@ -34,6 +34,7 @@ from lakefs_client.model.diff_list import DiffList from lakefs_client.model.error import Error from lakefs_client.model.error_no_acl import ErrorNoACL +from lakefs_client.model.external_login_information import ExternalLoginInformation from lakefs_client.model.external_principal import ExternalPrincipal from lakefs_client.model.external_principal_creation import ExternalPrincipalCreation from lakefs_client.model.external_principal_list import ExternalPrincipalList diff --git a/clients/python-legacy/test/test_auth_api.py b/clients/python-legacy/test/test_auth_api.py index 82ad0a11214..d35e074af90 100644 --- a/clients/python-legacy/test/test_auth_api.py +++ b/clients/python-legacy/test/test_auth_api.py @@ -136,6 +136,13 @@ def test_detach_policy_from_user(self): """ pass + def test_external_principal_login(self): + """Test case for external_principal_login + + perform a login using an external authenticator # noqa: E501 + """ + pass + def test_get_credentials(self): """Test case for get_credentials diff --git a/clients/python-legacy/test/test_experimental_api.py b/clients/python-legacy/test/test_experimental_api.py index 3337a175af2..e17d2876002 100644 --- a/clients/python-legacy/test/test_experimental_api.py +++ b/clients/python-legacy/test/test_experimental_api.py @@ -59,6 +59,13 @@ def test_delete_user_external_principal(self): """ pass + def test_external_principal_login(self): + """Test case for external_principal_login + + perform a login using an external authenticator # noqa: E501 + """ + pass + def test_get_external_principal(self): """Test case for get_external_principal diff --git a/clients/python-legacy/test/test_external_api.py b/clients/python-legacy/test/test_external_api.py index d07e73be645..9ca21eaad2c 100644 --- a/clients/python-legacy/test/test_external_api.py +++ b/clients/python-legacy/test/test_external_api.py @@ -38,6 +38,13 @@ def test_delete_user_external_principal(self): """ pass + def test_external_principal_login(self): + """Test case for external_principal_login + + perform a login using an external authenticator # noqa: E501 + """ + pass + def test_get_external_principal(self): """Test case for get_external_principal diff --git a/clients/python-legacy/test/test_external_login_information.py b/clients/python-legacy/test/test_external_login_information.py new file mode 100644 index 00000000000..2660def38f1 --- /dev/null +++ b/clients/python-legacy/test/test_external_login_information.py @@ -0,0 +1,36 @@ +""" + lakeFS API + + lakeFS HTTP API # noqa: E501 + + The version of the OpenAPI document: 1.0.0 + Contact: services@treeverse.io + Generated by: https://openapi-generator.tech +""" + + +import sys +import unittest + +import lakefs_client +from lakefs_client.model.external_login_information import ExternalLoginInformation + + +class TestExternalLoginInformation(unittest.TestCase): + """ExternalLoginInformation unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testExternalLoginInformation(self): + """Test ExternalLoginInformation""" + # FIXME: construct object with mandatory attributes with example values + # model = ExternalLoginInformation() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/clients/python/.openapi-generator/FILES b/clients/python/.openapi-generator/FILES index 75dd1cb6584..0d2e0450ebd 100644 --- a/clients/python/.openapi-generator/FILES +++ b/clients/python/.openapi-generator/FILES @@ -32,6 +32,7 @@ docs/Error.md docs/ErrorNoACL.md docs/ExperimentalApi.md docs/ExternalApi.md +docs/ExternalLoginInformation.md docs/ExternalPrincipal.md docs/ExternalPrincipalCreation.md docs/ExternalPrincipalList.md @@ -162,6 +163,7 @@ lakefs_sdk/models/diff.py lakefs_sdk/models/diff_list.py lakefs_sdk/models/error.py lakefs_sdk/models/error_no_acl.py +lakefs_sdk/models/external_login_information.py lakefs_sdk/models/external_principal.py lakefs_sdk/models/external_principal_creation.py lakefs_sdk/models/external_principal_list.py @@ -274,6 +276,7 @@ test/test_error.py test/test_error_no_acl.py test/test_experimental_api.py test/test_external_api.py +test/test_external_login_information.py test/test_external_principal.py test/test_external_principal_creation.py test/test_external_principal_list.py diff --git a/clients/python/README.md b/clients/python/README.md index 74a7df8ae9e..c13eee0dbe3 100644 --- a/clients/python/README.md +++ b/clients/python/README.md @@ -139,6 +139,7 @@ Class | Method | HTTP request | Description *AuthApi* | [**delete_user_external_principal**](docs/AuthApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user *AuthApi* | [**detach_policy_from_group**](docs/AuthApi.md#detach_policy_from_group) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group *AuthApi* | [**detach_policy_from_user**](docs/AuthApi.md#detach_policy_from_user) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user +*AuthApi* | [**external_principal_login**](docs/AuthApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator *AuthApi* | [**get_credentials**](docs/AuthApi.md#get_credentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials *AuthApi* | [**get_current_user**](docs/AuthApi.md#get_current_user) | **GET** /user | get current user *AuthApi* | [**get_external_principal**](docs/AuthApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id @@ -174,12 +175,14 @@ Class | Method | HTTP request | Description *ExperimentalApi* | [**create_presign_multipart_upload**](docs/ExperimentalApi.md#create_presign_multipart_upload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload *ExperimentalApi* | [**create_user_external_principal**](docs/ExperimentalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExperimentalApi* | [**delete_user_external_principal**](docs/ExperimentalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExperimentalApi* | [**external_principal_login**](docs/ExperimentalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExperimentalApi* | [**get_external_principal**](docs/ExperimentalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id *ExperimentalApi* | [**hard_reset_branch**](docs/ExperimentalApi.md#hard_reset_branch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch *ExperimentalApi* | [**list_user_external_principals**](docs/ExperimentalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *ExperimentalApi* | [**sts_login**](docs/ExperimentalApi.md#sts_login) | **POST** /sts/login | perform a login with STS *ExternalApi* | [**create_user_external_principal**](docs/ExternalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user *ExternalApi* | [**delete_user_external_principal**](docs/ExternalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +*ExternalApi* | [**external_principal_login**](docs/ExternalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator *ExternalApi* | [**get_external_principal**](docs/ExternalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id *ExternalApi* | [**list_user_external_principals**](docs/ExternalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user *HealthCheckApi* | [**health_check**](docs/HealthCheckApi.md#health_check) | **GET** /healthcheck | @@ -277,6 +280,7 @@ Class | Method | HTTP request | Description - [DiffList](docs/DiffList.md) - [Error](docs/Error.md) - [ErrorNoACL](docs/ErrorNoACL.md) + - [ExternalLoginInformation](docs/ExternalLoginInformation.md) - [ExternalPrincipal](docs/ExternalPrincipal.md) - [ExternalPrincipalCreation](docs/ExternalPrincipalCreation.md) - [ExternalPrincipalList](docs/ExternalPrincipalList.md) diff --git a/clients/python/docs/AuthApi.md b/clients/python/docs/AuthApi.md index bd9416ecbfd..dfd5f7b2a63 100644 --- a/clients/python/docs/AuthApi.md +++ b/clients/python/docs/AuthApi.md @@ -20,6 +20,7 @@ Method | HTTP request | Description [**delete_user_external_principal**](AuthApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user [**detach_policy_from_group**](AuthApi.md#detach_policy_from_group) | **DELETE** /auth/groups/{groupId}/policies/{policyId} | detach policy from group [**detach_policy_from_user**](AuthApi.md#detach_policy_from_user) | **DELETE** /auth/users/{userId}/policies/{policyId} | detach policy from user +[**external_principal_login**](AuthApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**get_credentials**](AuthApi.md#get_credentials) | **GET** /auth/users/{userId}/credentials/{accessKeyId} | get credentials [**get_current_user**](AuthApi.md#get_current_user) | **GET** /user | get current user [**get_external_principal**](AuthApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id @@ -1791,6 +1792,81 @@ void (empty response body) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **external_principal_login** +> AuthenticationToken external_principal_login(external_login_information=external_login_information) + +perform a login using an external authenticator + +### Example + + +```python +import time +import os +import lakefs_sdk +from lakefs_sdk.models.authentication_token import AuthenticationToken +from lakefs_sdk.models.external_login_information import ExternalLoginInformation +from lakefs_sdk.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to /api/v1 +# See configuration.py for a list of all supported configuration parameters. +configuration = lakefs_sdk.Configuration( + host = "/api/v1" +) + + +# Enter a context with an instance of the API client +with lakefs_sdk.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = lakefs_sdk.AuthApi(api_client) + external_login_information = lakefs_sdk.ExternalLoginInformation() # ExternalLoginInformation | (optional) + + try: + # perform a login using an external authenticator + api_response = api_instance.external_principal_login(external_login_information=external_login_information) + print("The response of AuthApi->external_principal_login:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling AuthApi->external_principal_login: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **external_login_information** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **get_credentials** > Credentials get_credentials(user_id, access_key_id) diff --git a/clients/python/docs/ExperimentalApi.md b/clients/python/docs/ExperimentalApi.md index 48fda6435a7..bcff98cba07 100644 --- a/clients/python/docs/ExperimentalApi.md +++ b/clients/python/docs/ExperimentalApi.md @@ -9,6 +9,7 @@ Method | HTTP request | Description [**create_presign_multipart_upload**](ExperimentalApi.md#create_presign_multipart_upload) | **POST** /repositories/{repository}/branches/{branch}/staging/pmpu | Initiate a multipart upload [**create_user_external_principal**](ExperimentalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user [**delete_user_external_principal**](ExperimentalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +[**external_principal_login**](ExperimentalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**get_external_principal**](ExperimentalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id [**hard_reset_branch**](ExperimentalApi.md#hard_reset_branch) | **PUT** /repositories/{repository}/branches/{branch}/hard_reset | hard reset branch [**list_user_external_principals**](ExperimentalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user @@ -598,6 +599,81 @@ void (empty response body) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **external_principal_login** +> AuthenticationToken external_principal_login(external_login_information=external_login_information) + +perform a login using an external authenticator + +### Example + + +```python +import time +import os +import lakefs_sdk +from lakefs_sdk.models.authentication_token import AuthenticationToken +from lakefs_sdk.models.external_login_information import ExternalLoginInformation +from lakefs_sdk.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to /api/v1 +# See configuration.py for a list of all supported configuration parameters. +configuration = lakefs_sdk.Configuration( + host = "/api/v1" +) + + +# Enter a context with an instance of the API client +with lakefs_sdk.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = lakefs_sdk.ExperimentalApi(api_client) + external_login_information = lakefs_sdk.ExternalLoginInformation() # ExternalLoginInformation | (optional) + + try: + # perform a login using an external authenticator + api_response = api_instance.external_principal_login(external_login_information=external_login_information) + print("The response of ExperimentalApi->external_principal_login:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling ExperimentalApi->external_principal_login: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **external_login_information** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **get_external_principal** > ExternalPrincipal get_external_principal(principal_id) @@ -1008,6 +1084,7 @@ No authorization required |-------------|-------------|------------------| **200** | successful STS login | - | **401** | Unauthorized | - | +**420** | too many requests | - | **0** | Internal Server Error | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/clients/python/docs/ExternalApi.md b/clients/python/docs/ExternalApi.md index 29a7642080c..f65514dc4f1 100644 --- a/clients/python/docs/ExternalApi.md +++ b/clients/python/docs/ExternalApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**create_user_external_principal**](ExternalApi.md#create_user_external_principal) | **POST** /auth/users/{userId}/external/principals | attach external principal to user [**delete_user_external_principal**](ExternalApi.md#delete_user_external_principal) | **DELETE** /auth/users/{userId}/external/principals | delete external principal from user +[**external_principal_login**](ExternalApi.md#external_principal_login) | **POST** /auth/external/principal/login | perform a login using an external authenticator [**get_external_principal**](ExternalApi.md#get_external_principal) | **GET** /auth/external/principals | describe external principal by id [**list_user_external_principals**](ExternalApi.md#list_user_external_principals) | **GET** /auth/users/{userId}/external/principals/ls | list user external policies attached to a user @@ -232,6 +233,81 @@ void (empty response body) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **external_principal_login** +> AuthenticationToken external_principal_login(external_login_information=external_login_information) + +perform a login using an external authenticator + +### Example + + +```python +import time +import os +import lakefs_sdk +from lakefs_sdk.models.authentication_token import AuthenticationToken +from lakefs_sdk.models.external_login_information import ExternalLoginInformation +from lakefs_sdk.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to /api/v1 +# See configuration.py for a list of all supported configuration parameters. +configuration = lakefs_sdk.Configuration( + host = "/api/v1" +) + + +# Enter a context with an instance of the API client +with lakefs_sdk.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = lakefs_sdk.ExternalApi(api_client) + external_login_information = lakefs_sdk.ExternalLoginInformation() # ExternalLoginInformation | (optional) + + try: + # perform a login using an external authenticator + api_response = api_instance.external_principal_login(external_login_information=external_login_information) + print("The response of ExternalApi->external_principal_login:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling ExternalApi->external_principal_login: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **external_login_information** | [**ExternalLoginInformation**](ExternalLoginInformation.md)| | [optional] + +### Return type + +[**AuthenticationToken**](AuthenticationToken.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | successful external login | - | +**400** | Bad Request | - | +**401** | Unauthorized | - | +**403** | Forbidden | - | +**404** | Resource Not Found | - | +**420** | too many requests | - | +**0** | Internal Server Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **get_external_principal** > ExternalPrincipal get_external_principal(principal_id) diff --git a/clients/python/docs/ExternalLoginInformation.md b/clients/python/docs/ExternalLoginInformation.md new file mode 100644 index 00000000000..8b454d9335a --- /dev/null +++ b/clients/python/docs/ExternalLoginInformation.md @@ -0,0 +1,30 @@ +# ExternalLoginInformation + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**token_expiration_duration** | **int** | | [optional] +**identity_request** | **object** | | + +## Example + +```python +from lakefs_sdk.models.external_login_information import ExternalLoginInformation + +# TODO update the JSON string below +json = "{}" +# create an instance of ExternalLoginInformation from a JSON string +external_login_information_instance = ExternalLoginInformation.from_json(json) +# print the JSON string representation of the object +print ExternalLoginInformation.to_json() + +# convert the object into a dict +external_login_information_dict = external_login_information_instance.to_dict() +# create an instance of ExternalLoginInformation from a dict +external_login_information_form_dict = external_login_information.from_dict(external_login_information_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/clients/python/docs/StsAuthRequest.md b/clients/python/docs/StsAuthRequest.md index 430a34cdc0c..2ec418f8f36 100644 --- a/clients/python/docs/StsAuthRequest.md +++ b/clients/python/docs/StsAuthRequest.md @@ -8,7 +8,7 @@ Name | Type | Description | Notes **code** | **str** | | **state** | **str** | | **redirect_uri** | **str** | | -**ttl_seconds** | **int** | The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. | [optional] +**ttl_seconds** | **int** | The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. | [optional] ## Example diff --git a/clients/python/lakefs_sdk/__init__.py b/clients/python/lakefs_sdk/__init__.py index ec354e5f9bb..4527c35ba0f 100644 --- a/clients/python/lakefs_sdk/__init__.py +++ b/clients/python/lakefs_sdk/__init__.py @@ -72,6 +72,7 @@ from lakefs_sdk.models.diff_list import DiffList from lakefs_sdk.models.error import Error from lakefs_sdk.models.error_no_acl import ErrorNoACL +from lakefs_sdk.models.external_login_information import ExternalLoginInformation from lakefs_sdk.models.external_principal import ExternalPrincipal from lakefs_sdk.models.external_principal_creation import ExternalPrincipalCreation from lakefs_sdk.models.external_principal_list import ExternalPrincipalList diff --git a/clients/python/lakefs_sdk/api/auth_api.py b/clients/python/lakefs_sdk/api/auth_api.py index d7a68967d37..d289979a193 100644 --- a/clients/python/lakefs_sdk/api/auth_api.py +++ b/clients/python/lakefs_sdk/api/auth_api.py @@ -30,6 +30,7 @@ from lakefs_sdk.models.credentials_list import CredentialsList from lakefs_sdk.models.credentials_with_secret import CredentialsWithSecret from lakefs_sdk.models.current_user import CurrentUser +from lakefs_sdk.models.external_login_information import ExternalLoginInformation from lakefs_sdk.models.external_principal import ExternalPrincipal from lakefs_sdk.models.external_principal_creation import ExternalPrincipalCreation from lakefs_sdk.models.external_principal_list import ExternalPrincipalList @@ -2353,6 +2354,155 @@ def detach_policy_from_user_with_http_info(self, user_id : StrictStr, policy_id collection_formats=_collection_formats, _request_auth=_params.get('_request_auth')) + @validate_arguments + def external_principal_login(self, external_login_information : Optional[ExternalLoginInformation] = None, **kwargs) -> AuthenticationToken: # noqa: E501 + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login(external_login_information, async_req=True) + >>> result = thread.get() + + :param external_login_information: + :type external_login_information: ExternalLoginInformation + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: AuthenticationToken + """ + kwargs['_return_http_data_only'] = True + if '_preload_content' in kwargs: + raise ValueError("Error! Please call the external_principal_login_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data") + return self.external_principal_login_with_http_info(external_login_information, **kwargs) # noqa: E501 + + @validate_arguments + def external_principal_login_with_http_info(self, external_login_information : Optional[ExternalLoginInformation] = None, **kwargs) -> ApiResponse: # noqa: E501 + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login_with_http_info(external_login_information, async_req=True) + >>> result = thread.get() + + :param external_login_information: + :type external_login_information: ExternalLoginInformation + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _preload_content: if False, the ApiResponse.data will + be set to none and raw_data will store the + HTTP response body without reading/decoding. + Default is True. + :type _preload_content: bool, optional + :param _return_http_data_only: response data instead of ApiResponse + object with status code, headers, etc + :type _return_http_data_only: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :type _request_auth: dict, optional + :type _content_type: string, optional: force content-type for the request + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: tuple(AuthenticationToken, status_code(int), headers(HTTPHeaderDict)) + """ + + _params = locals() + + _all_params = [ + 'external_login_information' + ] + _all_params.extend( + [ + 'async_req', + '_return_http_data_only', + '_preload_content', + '_request_timeout', + '_request_auth', + '_content_type', + '_headers' + ] + ) + + # validate the arguments + for _key, _val in _params['kwargs'].items(): + if _key not in _all_params: + raise ApiTypeError( + "Got an unexpected keyword argument '%s'" + " to method external_principal_login" % _key + ) + _params[_key] = _val + del _params['kwargs'] + + _collection_formats = {} + + # process the path parameters + _path_params = {} + + # process the query parameters + _query_params = [] + # process the header parameters + _header_params = dict(_params.get('_headers', {})) + # process the form parameters + _form_params = [] + _files = {} + # process the body parameter + _body_params = None + if _params['external_login_information'] is not None: + _body_params = _params['external_login_information'] + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # set the HTTP header `Content-Type` + _content_types_list = _params.get('_content_type', + self.api_client.select_header_content_type( + ['application/json'])) + if _content_types_list: + _header_params['Content-Type'] = _content_types_list + + # authentication setting + _auth_settings = [] # noqa: E501 + + _response_types_map = { + '200': "AuthenticationToken", + '400': "Error", + '401': "Error", + '403': "Error", + '404': "Error", + '420': None, + } + + return self.api_client.call_api( + '/auth/external/principal/login', 'POST', + _path_params, + _query_params, + _header_params, + body=_body_params, + post_params=_form_params, + files=_files, + response_types_map=_response_types_map, + auth_settings=_auth_settings, + async_req=_params.get('async_req'), + _return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501 + _preload_content=_params.get('_preload_content', True), + _request_timeout=_params.get('_request_timeout'), + collection_formats=_collection_formats, + _request_auth=_params.get('_request_auth')) + @validate_arguments def get_credentials(self, user_id : StrictStr, access_key_id : StrictStr, **kwargs) -> Credentials: # noqa: E501 """get credentials # noqa: E501 diff --git a/clients/python/lakefs_sdk/api/experimental_api.py b/clients/python/lakefs_sdk/api/experimental_api.py index aa75e9e789a..66ffe65c9a0 100644 --- a/clients/python/lakefs_sdk/api/experimental_api.py +++ b/clients/python/lakefs_sdk/api/experimental_api.py @@ -27,6 +27,7 @@ from lakefs_sdk.models.abort_presign_multipart_upload import AbortPresignMultipartUpload from lakefs_sdk.models.authentication_token import AuthenticationToken from lakefs_sdk.models.complete_presign_multipart_upload import CompletePresignMultipartUpload +from lakefs_sdk.models.external_login_information import ExternalLoginInformation from lakefs_sdk.models.external_principal import ExternalPrincipal from lakefs_sdk.models.external_principal_creation import ExternalPrincipalCreation from lakefs_sdk.models.external_principal_list import ExternalPrincipalList @@ -881,6 +882,155 @@ def delete_user_external_principal_with_http_info(self, user_id : StrictStr, pri collection_formats=_collection_formats, _request_auth=_params.get('_request_auth')) + @validate_arguments + def external_principal_login(self, external_login_information : Optional[ExternalLoginInformation] = None, **kwargs) -> AuthenticationToken: # noqa: E501 + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login(external_login_information, async_req=True) + >>> result = thread.get() + + :param external_login_information: + :type external_login_information: ExternalLoginInformation + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: AuthenticationToken + """ + kwargs['_return_http_data_only'] = True + if '_preload_content' in kwargs: + raise ValueError("Error! Please call the external_principal_login_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data") + return self.external_principal_login_with_http_info(external_login_information, **kwargs) # noqa: E501 + + @validate_arguments + def external_principal_login_with_http_info(self, external_login_information : Optional[ExternalLoginInformation] = None, **kwargs) -> ApiResponse: # noqa: E501 + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login_with_http_info(external_login_information, async_req=True) + >>> result = thread.get() + + :param external_login_information: + :type external_login_information: ExternalLoginInformation + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _preload_content: if False, the ApiResponse.data will + be set to none and raw_data will store the + HTTP response body without reading/decoding. + Default is True. + :type _preload_content: bool, optional + :param _return_http_data_only: response data instead of ApiResponse + object with status code, headers, etc + :type _return_http_data_only: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :type _request_auth: dict, optional + :type _content_type: string, optional: force content-type for the request + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: tuple(AuthenticationToken, status_code(int), headers(HTTPHeaderDict)) + """ + + _params = locals() + + _all_params = [ + 'external_login_information' + ] + _all_params.extend( + [ + 'async_req', + '_return_http_data_only', + '_preload_content', + '_request_timeout', + '_request_auth', + '_content_type', + '_headers' + ] + ) + + # validate the arguments + for _key, _val in _params['kwargs'].items(): + if _key not in _all_params: + raise ApiTypeError( + "Got an unexpected keyword argument '%s'" + " to method external_principal_login" % _key + ) + _params[_key] = _val + del _params['kwargs'] + + _collection_formats = {} + + # process the path parameters + _path_params = {} + + # process the query parameters + _query_params = [] + # process the header parameters + _header_params = dict(_params.get('_headers', {})) + # process the form parameters + _form_params = [] + _files = {} + # process the body parameter + _body_params = None + if _params['external_login_information'] is not None: + _body_params = _params['external_login_information'] + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # set the HTTP header `Content-Type` + _content_types_list = _params.get('_content_type', + self.api_client.select_header_content_type( + ['application/json'])) + if _content_types_list: + _header_params['Content-Type'] = _content_types_list + + # authentication setting + _auth_settings = [] # noqa: E501 + + _response_types_map = { + '200': "AuthenticationToken", + '400': "Error", + '401': "Error", + '403': "Error", + '404': "Error", + '420': None, + } + + return self.api_client.call_api( + '/auth/external/principal/login', 'POST', + _path_params, + _query_params, + _header_params, + body=_body_params, + post_params=_form_params, + files=_files, + response_types_map=_response_types_map, + auth_settings=_auth_settings, + async_req=_params.get('async_req'), + _return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501 + _preload_content=_params.get('_preload_content', True), + _request_timeout=_params.get('_request_timeout'), + collection_formats=_collection_formats, + _request_auth=_params.get('_request_auth')) + @validate_arguments def get_external_principal(self, principal_id : StrictStr, **kwargs) -> ExternalPrincipal: # noqa: E501 """describe external principal by id # noqa: E501 @@ -1472,6 +1622,7 @@ def sts_login_with_http_info(self, sts_auth_request : StsAuthRequest, **kwargs) _response_types_map = { '200': "AuthenticationToken", '401': "Error", + '420': None, } return self.api_client.call_api( diff --git a/clients/python/lakefs_sdk/api/external_api.py b/clients/python/lakefs_sdk/api/external_api.py index 19384b63321..8b5462faff2 100644 --- a/clients/python/lakefs_sdk/api/external_api.py +++ b/clients/python/lakefs_sdk/api/external_api.py @@ -24,6 +24,8 @@ from typing import Optional +from lakefs_sdk.models.authentication_token import AuthenticationToken +from lakefs_sdk.models.external_login_information import ExternalLoginInformation from lakefs_sdk.models.external_principal import ExternalPrincipal from lakefs_sdk.models.external_principal_creation import ExternalPrincipalCreation from lakefs_sdk.models.external_principal_list import ExternalPrincipalList @@ -349,6 +351,155 @@ def delete_user_external_principal_with_http_info(self, user_id : StrictStr, pri collection_formats=_collection_formats, _request_auth=_params.get('_request_auth')) + @validate_arguments + def external_principal_login(self, external_login_information : Optional[ExternalLoginInformation] = None, **kwargs) -> AuthenticationToken: # noqa: E501 + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login(external_login_information, async_req=True) + >>> result = thread.get() + + :param external_login_information: + :type external_login_information: ExternalLoginInformation + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: AuthenticationToken + """ + kwargs['_return_http_data_only'] = True + if '_preload_content' in kwargs: + raise ValueError("Error! Please call the external_principal_login_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data") + return self.external_principal_login_with_http_info(external_login_information, **kwargs) # noqa: E501 + + @validate_arguments + def external_principal_login_with_http_info(self, external_login_information : Optional[ExternalLoginInformation] = None, **kwargs) -> ApiResponse: # noqa: E501 + """perform a login using an external authenticator # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.external_principal_login_with_http_info(external_login_information, async_req=True) + >>> result = thread.get() + + :param external_login_information: + :type external_login_information: ExternalLoginInformation + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional + :param _preload_content: if False, the ApiResponse.data will + be set to none and raw_data will store the + HTTP response body without reading/decoding. + Default is True. + :type _preload_content: bool, optional + :param _return_http_data_only: response data instead of ApiResponse + object with status code, headers, etc + :type _return_http_data_only: bool, optional + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :type _request_auth: dict, optional + :type _content_type: string, optional: force content-type for the request + :return: Returns the result object. + If the method is called asynchronously, + returns the request thread. + :rtype: tuple(AuthenticationToken, status_code(int), headers(HTTPHeaderDict)) + """ + + _params = locals() + + _all_params = [ + 'external_login_information' + ] + _all_params.extend( + [ + 'async_req', + '_return_http_data_only', + '_preload_content', + '_request_timeout', + '_request_auth', + '_content_type', + '_headers' + ] + ) + + # validate the arguments + for _key, _val in _params['kwargs'].items(): + if _key not in _all_params: + raise ApiTypeError( + "Got an unexpected keyword argument '%s'" + " to method external_principal_login" % _key + ) + _params[_key] = _val + del _params['kwargs'] + + _collection_formats = {} + + # process the path parameters + _path_params = {} + + # process the query parameters + _query_params = [] + # process the header parameters + _header_params = dict(_params.get('_headers', {})) + # process the form parameters + _form_params = [] + _files = {} + # process the body parameter + _body_params = None + if _params['external_login_information'] is not None: + _body_params = _params['external_login_information'] + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + ['application/json']) # noqa: E501 + + # set the HTTP header `Content-Type` + _content_types_list = _params.get('_content_type', + self.api_client.select_header_content_type( + ['application/json'])) + if _content_types_list: + _header_params['Content-Type'] = _content_types_list + + # authentication setting + _auth_settings = [] # noqa: E501 + + _response_types_map = { + '200': "AuthenticationToken", + '400': "Error", + '401': "Error", + '403': "Error", + '404': "Error", + '420': None, + } + + return self.api_client.call_api( + '/auth/external/principal/login', 'POST', + _path_params, + _query_params, + _header_params, + body=_body_params, + post_params=_form_params, + files=_files, + response_types_map=_response_types_map, + auth_settings=_auth_settings, + async_req=_params.get('async_req'), + _return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501 + _preload_content=_params.get('_preload_content', True), + _request_timeout=_params.get('_request_timeout'), + collection_formats=_collection_formats, + _request_auth=_params.get('_request_auth')) + @validate_arguments def get_external_principal(self, principal_id : StrictStr, **kwargs) -> ExternalPrincipal: # noqa: E501 """describe external principal by id # noqa: E501 diff --git a/clients/python/lakefs_sdk/models/__init__.py b/clients/python/lakefs_sdk/models/__init__.py index ac53774ac3a..943a4a52f39 100644 --- a/clients/python/lakefs_sdk/models/__init__.py +++ b/clients/python/lakefs_sdk/models/__init__.py @@ -40,6 +40,7 @@ from lakefs_sdk.models.diff_list import DiffList from lakefs_sdk.models.error import Error from lakefs_sdk.models.error_no_acl import ErrorNoACL +from lakefs_sdk.models.external_login_information import ExternalLoginInformation from lakefs_sdk.models.external_principal import ExternalPrincipal from lakefs_sdk.models.external_principal_creation import ExternalPrincipalCreation from lakefs_sdk.models.external_principal_list import ExternalPrincipalList diff --git a/clients/python/lakefs_sdk/models/external_login_information.py b/clients/python/lakefs_sdk/models/external_login_information.py new file mode 100644 index 00000000000..266b862dab0 --- /dev/null +++ b/clients/python/lakefs_sdk/models/external_login_information.py @@ -0,0 +1,74 @@ +# coding: utf-8 + +""" + lakeFS API + + lakeFS HTTP API + + The version of the OpenAPI document: 1.0.0 + Contact: services@treeverse.io + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, Dict, Optional +from pydantic import BaseModel, Field, StrictInt + +class ExternalLoginInformation(BaseModel): + """ + ExternalLoginInformation + """ + token_expiration_duration: Optional[StrictInt] = None + identity_request: Dict[str, Any] = Field(..., alias="identityRequest") + __properties = ["token_expiration_duration", "identityRequest"] + + class Config: + """Pydantic configuration""" + allow_population_by_field_name = True + validate_assignment = True + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.dict(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> ExternalLoginInformation: + """Create an instance of ExternalLoginInformation from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self): + """Returns the dictionary representation of the model using alias""" + _dict = self.dict(by_alias=True, + exclude={ + }, + exclude_none=True) + return _dict + + @classmethod + def from_dict(cls, obj: dict) -> ExternalLoginInformation: + """Create an instance of ExternalLoginInformation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return ExternalLoginInformation.parse_obj(obj) + + _obj = ExternalLoginInformation.parse_obj({ + "token_expiration_duration": obj.get("token_expiration_duration"), + "identity_request": obj.get("identityRequest") + }) + return _obj + + diff --git a/clients/python/lakefs_sdk/models/sts_auth_request.py b/clients/python/lakefs_sdk/models/sts_auth_request.py index c588f98d3f0..7ae48616940 100644 --- a/clients/python/lakefs_sdk/models/sts_auth_request.py +++ b/clients/python/lakefs_sdk/models/sts_auth_request.py @@ -29,7 +29,7 @@ class StsAuthRequest(BaseModel): code: StrictStr = Field(...) state: StrictStr = Field(...) redirect_uri: StrictStr = Field(...) - ttl_seconds: Optional[StrictInt] = Field(None, description="The time-to-live for the generated token in seconds. The maximum value is 3600 seconds (1 hour) max is 12 hours. ") + ttl_seconds: Optional[StrictInt] = Field(None, description="The time-to-live for the generated token in seconds. The default value is 3600 seconds (1 hour) maximum time allowed is 12 hours. ") __properties = ["code", "state", "redirect_uri", "ttl_seconds"] class Config: diff --git a/clients/python/test/test_auth_api.py b/clients/python/test/test_auth_api.py index 0438975ef2f..96dfe3671c5 100644 --- a/clients/python/test/test_auth_api.py +++ b/clients/python/test/test_auth_api.py @@ -141,6 +141,13 @@ def test_detach_policy_from_user(self): """ pass + def test_external_principal_login(self): + """Test case for external_principal_login + + perform a login using an external authenticator # noqa: E501 + """ + pass + def test_get_credentials(self): """Test case for get_credentials diff --git a/clients/python/test/test_experimental_api.py b/clients/python/test/test_experimental_api.py index f694e8cc23c..a831f98a15e 100644 --- a/clients/python/test/test_experimental_api.py +++ b/clients/python/test/test_experimental_api.py @@ -64,6 +64,13 @@ def test_delete_user_external_principal(self): """ pass + def test_external_principal_login(self): + """Test case for external_principal_login + + perform a login using an external authenticator # noqa: E501 + """ + pass + def test_get_external_principal(self): """Test case for get_external_principal diff --git a/clients/python/test/test_external_api.py b/clients/python/test/test_external_api.py index 946919f1f46..ba3a4b93e16 100644 --- a/clients/python/test/test_external_api.py +++ b/clients/python/test/test_external_api.py @@ -43,6 +43,13 @@ def test_delete_user_external_principal(self): """ pass + def test_external_principal_login(self): + """Test case for external_principal_login + + perform a login using an external authenticator # noqa: E501 + """ + pass + def test_get_external_principal(self): """Test case for get_external_principal diff --git a/clients/python/test/test_external_login_information.py b/clients/python/test/test_external_login_information.py new file mode 100644 index 00000000000..b2cfb95eb4f --- /dev/null +++ b/clients/python/test/test_external_login_information.py @@ -0,0 +1,57 @@ +# coding: utf-8 + +""" + lakeFS API + + lakeFS HTTP API + + The version of the OpenAPI document: 1.0.0 + Contact: services@treeverse.io + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +import lakefs_sdk +from lakefs_sdk.models.external_login_information import ExternalLoginInformation # noqa: E501 +from lakefs_sdk.rest import ApiException + +class TestExternalLoginInformation(unittest.TestCase): + """ExternalLoginInformation unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional): + """Test ExternalLoginInformation + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `ExternalLoginInformation` + """ + model = lakefs_sdk.models.external_login_information.ExternalLoginInformation() # noqa: E501 + if include_optional : + return ExternalLoginInformation( + token_expiration_duration = 56, + identity_request = None + ) + else : + return ExternalLoginInformation( + identity_request = None, + ) + """ + + def testExternalLoginInformation(self): + """Test ExternalLoginInformation""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/cmd/lakefs/cmd/run.go b/cmd/lakefs/cmd/run.go index c8221095635..ac994a88f0c 100644 --- a/cmd/lakefs/cmd/run.go +++ b/cmd/lakefs/cmd/run.go @@ -121,7 +121,7 @@ var runCmd = &cobra.Command{ apiService, err := auth.NewAPIAuthService( cfg.Auth.API.Endpoint, cfg.Auth.API.Token.SecureValue(), - cfg.Auth.RemoteAuthenticator.ExternalPrincipalsEnabled, + cfg.Auth.AuthenticationAPI.ExternalPrincipalsEnabled, crypt.NewSecretStore([]byte(cfg.Auth.Encrypt.SecretKey)), authparams.ServiceCache(cfg.Auth.Cache), logger.WithField("service", "auth_api"), @@ -146,7 +146,7 @@ var runCmd = &cobra.Command{ // initialize authentication service var authenticationService authentication.Service if cfg.IsAuthenticationTypeAPI() { - authenticationService, err = authentication.NewAPIService(cfg.Auth.AuthenticationAPI.Endpoint, cfg.Auth.CookieAuthVerification.ValidateIDTokenClaims, logger.WithField("service", "authentication_api")) + authenticationService, err = authentication.NewAPIService(cfg.Auth.AuthenticationAPI.Endpoint, cfg.Auth.CookieAuthVerification.ValidateIDTokenClaims, logger.WithField("service", "authentication_api"), cfg.Auth.AuthenticationAPI.ExternalPrincipalsEnabled) if err != nil { logger.WithError(err).Fatal("failed to create authentication service") } diff --git a/docs/assets/js/swagger.yml b/docs/assets/js/swagger.yml index bb163b02346..fb011a03ac0 100644 --- a/docs/assets/js/swagger.yml +++ b/docs/assets/js/swagger.yml @@ -38,6 +38,7 @@ components: type: apiKey in: cookie name: saml_auth_session + parameters: PaginationPrefix: in: query @@ -1049,6 +1050,17 @@ components: type: string secret_access_key: type: string + + ExternalLoginInformation: + type: object + required: + - identityRequest + properties: + token_expiration_duration: + type: integer + identityRequest: + type: object + StsAuthRequest: type: object required: @@ -1820,11 +1832,46 @@ paths: description: too many requests default: $ref: "#/components/responses/ServerError" + + /auth/external/principal/login: + post: + tags: + - external + - experimental + - auth + operationId: externalPrincipalLogin + summary: perform a login using an external authenticator + security: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ExternalLoginInformation" + responses: + 200: + description: successful external login + content: + application/json: + schema: + $ref: "#/components/schemas/AuthenticationToken" + 400: + $ref: "#/components/responses/BadRequest" + 401: + $ref: "#/components/responses/Unauthorized" + 403: + $ref: "#/components/responses/Forbidden" + 404: + $ref: "#/components/responses/NotFound" + 420: + description: too many requests + default: + $ref: "#/components/responses/ServerError" + /sts/login: post: tags: - experimental - operationId: stsLogin + operationId: stsLogin # change to stsLogin summary: perform a login with STS security: [] requestBody: @@ -1842,10 +1889,11 @@ paths: $ref: "#/components/schemas/AuthenticationToken" 401: $ref: "#/components/responses/Unauthorized" + 420: + description: too many requests default: $ref: "#/components/responses/ServerError" - /auth/capabilities: get: tags: diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 5134bc9ca42..83e4e15472c 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -83,17 +83,19 @@ This reference uses `.` to denote the nesting of values. * `auth.cache.ttl` `(time duration : "20s")` - How long to store an item in the auth cache. Using a higher value reduces load on the database, but will cause changes longer to take effect for cached users. * `auth.cache.jitter` `(time duration : "3s")` - A random amount of time between 0 and this value is added to each item's TTL. This is done to avoid a large bulk of keys expiring at once and overwhelming the database. * `auth.encrypt.secret_key` `(string : required)` - A random (cryptographically safe) generated string that is used for encryption and HMAC signing + **Note:** It is best to keep this somewhere safe such as KMS or Hashicorp Vault, and provide it to the system at run time + {: .note } + * `auth.login_duration` `(time duration : "168h")` - The duration the login token is valid for +* `auth.login_max_duration` `(time duration : "168h")` - The maximum duration user can ask for a login token * `auth.cookie_domain` `(string : "")` - [Domain attribute](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent) to set the access_token cookie on (the default is an empty string which defaults to the same host that sets the cookie) * `auth.api.endpoint` `(string: https://external.service/api/v1)` - URL to external Authorization Service described at [authorization.yml](https://github.com/treeverse/lakeFS/blob/master/api/authorization.yml); * `auth.api.token` `(string: eyJhbGciOiJIUzI1NiIsInR5...)` - API token used to authenticate requests to api endpoint * `auth.api.health_check_timeout` `(time duration : "20s")` - Timeout duration for external auth API health check * `auth.api.skip_health_check` `(bool : false)` - Skip external auth API health check - - **Note:** It is best to keep this somewhere safe such as KMS or Hashicorp Vault, and provide it to the system at run time - {: .note } +* `auth.authentication_api.endpoint` `(string : "")` - URL to external Authentication Service described at [authentication.yml](https://github.com/treeverse/lakeFS/blob/master/api/authentication.yml); +* `auth.authentication_api.external_principals_enabled` `(bool : false)` - If true, external principals API will be enabled, e.g auth service and login api's. * `auth.remote_authenticator.enabled` `(bool : false)` - If specified, also authenticate users via this Remote Authenticator server. -* `auth.remote_authenticator.external_principals_enabled` `(bool : false)` - If true, external principals will be enabled, e.g auth service and login api's. * `auth.remote_authenticator.endpoint` `(string : required)` - Endpoint URL of the remote authentication service (e.g. https://my-auth.example.com/auth). * `auth.remote_authenticator.default_user_group` `(string : Viewers)` - Create users in this group (i.e `Viewers`, `Developers`, etc). * `auth.remote_authenticator.request_timeout` `(duration : 10s)` - If specified, timeout for remote authentication requests. diff --git a/pkg/api/controller.go b/pkg/api/controller.go index b66312d780a..91072954335 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -559,6 +559,50 @@ func (c *Controller) Login(w http.ResponseWriter, r *http.Request, body apigen.L writeResponse(w, r, http.StatusOK, response) } +func (c *Controller) ExternalPrincipalLogin(w http.ResponseWriter, r *http.Request, body apigen.ExternalPrincipalLoginJSONRequestBody) { + ctx := r.Context() + if c.isExternalPrincipalNotSupported(ctx) { + writeError(w, r, http.StatusNotImplemented, "Not implemented") + return + } + c.LogAction(ctx, "external_principal_login", r, "", "", "") + c.Logger.Debug("external principal login") + externalPrincipal, err := c.Authentication.ExternalPrincipalLogin(ctx, body.IdentityRequest) + if c.handleAPIError(ctx, w, r, err) { + c.Logger.WithError(err).Error("external principal login failed") + return + } + c.Logger.WithField("external_principal_id", externalPrincipal.Id).Debug("external principal login success, trying to get external principal ID info") + externalPrincipalIDInfo, err := c.Auth.GetExternalPrincipal(ctx, externalPrincipal.Id) + if c.handleAPIError(ctx, w, r, err) { + c.Logger.WithField("external_principal_id", externalPrincipal.Id).WithError(err).Error("failed to get external principal ID info") + return + } + c.Logger.WithField("user_id", externalPrincipalIDInfo.UserID).Debug("got external principal ID info, generating a new JWT") + duration := c.Config.Auth.LoginDuration + if swag.IntValue(body.TokenExpirationDuration) > 0 { + duration = time.Second * time.Duration(*body.TokenExpirationDuration) + } + if duration > c.Config.Auth.LoginMaxDuration { + c.Logger.WithFields(logging.Fields{"duration": duration, "max_duration": c.Config.Auth.LoginMaxDuration}).Warn("Login duration exceeds maximum allowed, using maximum allowed") + duration = c.Config.Auth.LoginMaxDuration + } + loginTime := time.Now() + expires := loginTime.Add(duration) + secret := c.Auth.SecretStore().SharedSecret() + tokenString, err := GenerateJWTLogin(secret, externalPrincipalIDInfo.UserID, loginTime, expires) + if err != nil { + c.Logger.WithField("user_id", externalPrincipalIDInfo.UserID).WithError(err).Error("failed to generate JWT") + writeError(w, r, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + return + } + response := apigen.AuthenticationToken{ + Token: tokenString, + TokenExpiration: swag.Int64(expires.Unix()), + } + writeResponse(w, r, http.StatusOK, response) +} + func (c *Controller) StsLogin(w http.ResponseWriter, r *http.Request, body apigen.StsLoginJSONRequestBody) { ctx := r.Context() externalUserID, err := c.Authentication.ValidateSTS(ctx, body.Code, body.RedirectUri, body.State) @@ -2605,6 +2649,12 @@ func (c *Controller) handleAPIErrorCallback(ctx context.Context, w http.Response errors.Is(err, graveler.ErrReadOnlyRepository): cb(w, r, http.StatusForbidden, err) + case errors.Is(err, authentication.ErrSessionExpired): + cb(w, r, http.StatusForbidden, "session expired") + + case errors.Is(err, authentication.ErrInvalidTokenFormat): + cb(w, r, http.StatusUnauthorized, "invalid token format") + case errors.Is(err, graveler.ErrDirtyBranch), errors.Is(err, graveler.ErrCommitMetaRangeDirtyBranch), errors.Is(err, graveler.ErrInvalidValue), @@ -2621,7 +2671,8 @@ func (c *Controller) handleAPIErrorCallback(ctx context.Context, w http.Response errors.Is(err, graveler.ErrCherryPickMergeNoParent), errors.Is(err, graveler.ErrInvalidMergeStrategy), errors.Is(err, block.ErrInvalidAddress), - errors.Is(err, block.ErrOperationNotSupported): + errors.Is(err, block.ErrOperationNotSupported), + errors.Is(err, authentication.ErrInvalidRequest): log.Debug("Bad request") cb(w, r, http.StatusBadRequest, err) diff --git a/pkg/auth/remoteauthenticator/authenticator.go b/pkg/auth/remoteauthenticator/authenticator.go index e79c0775bdd..2b59ddeb393 100644 --- a/pkg/auth/remoteauthenticator/authenticator.go +++ b/pkg/auth/remoteauthenticator/authenticator.go @@ -24,8 +24,6 @@ var ErrBadConfig = errors.New("invalid configuration") type AuthenticatorConfig struct { // Enabled if set true will enable authenticator Enabled bool - // ExternalPrincipalAuth support external principals - ExternalPrincipalsEnabled bool // Endpoint URL of the remote authentication service (e.g. https://my-auth.example.com/auth) Endpoint string // DefaultUserGroup is the default group for the users authenticated by the remote service diff --git a/pkg/auth/service.go b/pkg/auth/service.go index 46e1bb8f23e..687e24c1bb4 100644 --- a/pkg/auth/service.go +++ b/pkg/auth/service.go @@ -1196,11 +1196,11 @@ const ( ) type APIAuthService struct { - apiClient ClientWithResponsesInterface - secretStore crypt.SecretStore - logger logging.Logger - cache Cache - externalPrincipalseEnabled bool + apiClient ClientWithResponsesInterface + secretStore crypt.SecretStore + logger logging.Logger + cache Cache + externalPrincipalsEnabled bool } func (a *APIAuthService) InviteUser(ctx context.Context, email string) error { @@ -1983,7 +1983,7 @@ func (a *APIAuthService) CheckHealth(ctx context.Context, logger logging.Logger, } func (a *APIAuthService) IsExternalPrincipalsEnabled(ctx context.Context) bool { - return a.externalPrincipalseEnabled + return a.externalPrincipalsEnabled } func (a *APIAuthService) CreateUserExternalPrincipal(ctx context.Context, userID, principalID string) error { @@ -2092,11 +2092,11 @@ func NewAPIAuthService(apiEndpoint, token string, externalPrincipalseEnabled boo cache = &DummyCache{} } res := &APIAuthService{ - apiClient: client, - secretStore: secretStore, - logger: logger, - cache: cache, - externalPrincipalseEnabled: externalPrincipalseEnabled, + apiClient: client, + secretStore: secretStore, + logger: logger, + cache: cache, + externalPrincipalsEnabled: externalPrincipalseEnabled, } return res, nil } @@ -2135,10 +2135,10 @@ func NewAPIAuthServiceWithClient(client ClientWithResponsesInterface, externalPr cache = &DummyCache{} } return &APIAuthService{ - apiClient: client, - secretStore: secretStore, - cache: cache, - logger: logger, - externalPrincipalseEnabled: externalPrincipalseEnabled, + apiClient: client, + secretStore: secretStore, + cache: cache, + logger: logger, + externalPrincipalsEnabled: externalPrincipalseEnabled, }, nil } diff --git a/pkg/authentication/errors.go b/pkg/authentication/errors.go index 54cce837b86..859dad5168a 100644 --- a/pkg/authentication/errors.go +++ b/pkg/authentication/errors.go @@ -10,4 +10,6 @@ var ( ErrInsufficientPermissions = errors.New("insufficient permissions") ErrUnexpectedStatusCode = errors.New("unexpected status code") ErrInvalidRequest = errors.New("invalid request") + ErrSessionExpired = errors.New("session expired") + ErrInvalidTokenFormat = errors.New("invalid token format") ) diff --git a/pkg/authentication/mock/mock_authentication_client.go b/pkg/authentication/mock/mock_authentication_client.go index cc37b0c58de..dc01ba9865b 100644 --- a/pkg/authentication/mock/mock_authentication_client.go +++ b/pkg/authentication/mock/mock_authentication_client.go @@ -36,6 +36,46 @@ func (m *MockClientWithResponsesInterface) EXPECT() *MockClientWithResponsesInte return m.recorder } +// ExternalPrincipalLoginWithBodyWithResponse mocks base method. +func (m *MockClientWithResponsesInterface) ExternalPrincipalLoginWithBodyWithResponse(arg0 context.Context, arg1 string, arg2 io.Reader, arg3 ...apiclient.RequestEditorFn) (*apiclient.ExternalPrincipalLoginResponse, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1, arg2} + for _, a := range arg3 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExternalPrincipalLoginWithBodyWithResponse", varargs...) + ret0, _ := ret[0].(*apiclient.ExternalPrincipalLoginResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExternalPrincipalLoginWithBodyWithResponse indicates an expected call of ExternalPrincipalLoginWithBodyWithResponse. +func (mr *MockClientWithResponsesInterfaceMockRecorder) ExternalPrincipalLoginWithBodyWithResponse(arg0, arg1, arg2 interface{}, arg3 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1, arg2}, arg3...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExternalPrincipalLoginWithBodyWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).ExternalPrincipalLoginWithBodyWithResponse), varargs...) +} + +// ExternalPrincipalLoginWithResponse mocks base method. +func (m *MockClientWithResponsesInterface) ExternalPrincipalLoginWithResponse(arg0 context.Context, arg1 apiclient.ExternalPrincipalLoginJSONRequestBody, arg2 ...apiclient.RequestEditorFn) (*apiclient.ExternalPrincipalLoginResponse, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExternalPrincipalLoginWithResponse", varargs...) + ret0, _ := ret[0].(*apiclient.ExternalPrincipalLoginResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExternalPrincipalLoginWithResponse indicates an expected call of ExternalPrincipalLoginWithResponse. +func (mr *MockClientWithResponsesInterfaceMockRecorder) ExternalPrincipalLoginWithResponse(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExternalPrincipalLoginWithResponse", reflect.TypeOf((*MockClientWithResponsesInterface)(nil).ExternalPrincipalLoginWithResponse), varargs...) +} + // HealthCheckWithResponse mocks base method. func (m *MockClientWithResponsesInterface) HealthCheckWithResponse(arg0 context.Context, arg1 ...apiclient.RequestEditorFn) (*apiclient.HealthCheckResponse, error) { m.ctrl.T.Helper() diff --git a/pkg/authentication/service.go b/pkg/authentication/service.go index a9efdc8cd00..ac13f4f15f9 100644 --- a/pkg/authentication/service.go +++ b/pkg/authentication/service.go @@ -14,6 +14,8 @@ import ( ) type Service interface { + IsExternalPrincipalsEnabled() bool + ExternalPrincipalLogin(ctx context.Context, identityRequest map[string]interface{}) (*apiclient.ExternalPrincipal, error) // ValidateSTS validates the STS parameters and returns the external user ID ValidateSTS(ctx context.Context, code, redirectURI, state string) (string, error) } @@ -23,35 +25,47 @@ type DummyService struct{} func NewDummyService() *DummyService { return &DummyService{} } + func (d DummyService) ValidateSTS(ctx context.Context, code, redirectURI, state string) (string, error) { return "", ErrNotImplemented } +func (d DummyService) ExternalPrincipalLogin(_ context.Context, _ map[string]interface{}) (*apiclient.ExternalPrincipal, error) { + return nil, ErrNotImplemented +} + +func (d DummyService) IsExternalPrincipalsEnabled() bool { + return false +} + type APIService struct { - validateIDTokenClaims map[string]string - apiClient apiclient.ClientWithResponsesInterface - logger logging.Logger + validateIDTokenClaims map[string]string + apiClient apiclient.ClientWithResponsesInterface + logger logging.Logger + externalPrincipalsEnabled bool } -func NewAPIService(apiEndpoint string, validateIDTokenClaims map[string]string, logger logging.Logger) (*APIService, error) { +func NewAPIService(apiEndpoint string, validateIDTokenClaims map[string]string, logger logging.Logger, externalPrincipalsEnabled bool) (*APIService, error) { client, err := apiclient.NewClientWithResponses(apiEndpoint) if err != nil { return nil, fmt.Errorf("failed to create authentication api client: %w", err) } res := &APIService{ - validateIDTokenClaims: validateIDTokenClaims, - apiClient: client, - logger: logger, + validateIDTokenClaims: validateIDTokenClaims, + apiClient: client, + logger: logger, + externalPrincipalsEnabled: externalPrincipalsEnabled, } return res, nil } -func NewAPIServiceWithClients(apiClient apiclient.ClientWithResponsesInterface, logger logging.Logger, validateIDTokenClaims map[string]string) (*APIService, error) { +func NewAPIServiceWithClients(apiClient apiclient.ClientWithResponsesInterface, logger logging.Logger, validateIDTokenClaims map[string]string, externalPrincipalsEnabled bool) (*APIService, error) { return &APIService{ - apiClient: apiClient, - logger: logger, - validateIDTokenClaims: validateIDTokenClaims, + apiClient: apiClient, + logger: logger, + validateIDTokenClaims: validateIDTokenClaims, + externalPrincipalsEnabled: externalPrincipalsEnabled, }, nil } @@ -102,3 +116,30 @@ func (s *APIService) ValidateSTS(ctx context.Context, code, redirectURI, state s } return subject, nil } + +func (s *APIService) ExternalPrincipalLogin(ctx context.Context, identityRequest map[string]interface{}) (*apiclient.ExternalPrincipal, error) { + if !s.IsExternalPrincipalsEnabled() { + return nil, fmt.Errorf("external principals disabled: %w", ErrInvalidRequest) + } + resp, err := s.apiClient.ExternalPrincipalLoginWithResponse(ctx, identityRequest) + if err != nil { + return nil, fmt.Errorf("calling authenticate user: %w", err) + } + if resp.StatusCode() != http.StatusOK { + switch resp.StatusCode() { + case http.StatusBadRequest: + return nil, ErrInvalidRequest + case http.StatusUnauthorized: + return nil, ErrInvalidTokenFormat + case http.StatusForbidden: + return nil, ErrSessionExpired + default: + return nil, fmt.Errorf("%w - got %d expected %d", ErrUnexpectedStatusCode, resp.StatusCode(), http.StatusOK) + } + } + return resp.JSON200, nil +} + +func (s *APIService) IsExternalPrincipalsEnabled() bool { + return s.externalPrincipalsEnabled +} diff --git a/pkg/authentication/service_test.go b/pkg/authentication/service_test.go index 78bf8821094..6235f9abb8c 100644 --- a/pkg/authentication/service_test.go +++ b/pkg/authentication/service_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" "github.com/treeverse/lakefs/pkg/authentication" "github.com/treeverse/lakefs/pkg/authentication/apiclient" "github.com/treeverse/lakefs/pkg/authentication/mock" @@ -79,7 +80,7 @@ func TestAPIAuthService_STSLogin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { validateTokenClaims := map[string]string{tt.validateClaim: tt.validateClaimValue} - mockClient, s := NewTestApiService(t, validateTokenClaims) + mockClient, s := NewTestApiService(t, validateTokenClaims, false) ctx := context.Background() requestEq := gomock.Eq(apiclient.STSLoginJSONRequestBody{ RedirectUri: redirectURI, @@ -120,13 +121,32 @@ func TestAPIAuthService_STSLogin(t *testing.T) { } } -func NewTestApiService(t *testing.T, validateIDTokenClaims map[string]string) (*mock.MockClientWithResponsesInterface, *authentication.APIService) { +func NewTestApiService(t *testing.T, validateIDTokenClaims map[string]string, externalPrincipalsEnabled bool) (*mock.MockClientWithResponsesInterface, *authentication.APIService) { t.Helper() ctrl := gomock.NewController(t) mockClient := mock.NewMockClientWithResponsesInterface(ctrl) - s, err := authentication.NewAPIServiceWithClients(mockClient, logging.ContextUnavailable(), validateIDTokenClaims) + s, err := authentication.NewAPIServiceWithClients(mockClient, logging.ContextUnavailable(), validateIDTokenClaims, externalPrincipalsEnabled) if err != nil { t.Fatalf("failed initiating API service with mock") } return mockClient, s } + +func TestAPIAuthService_ExternalLogin(t *testing.T) { + mockClient, s := NewTestApiService(t, map[string]string{}, true) + ctx := context.Background() + principalId := "arn" + externalLoginInfo := map[string]interface{}{"IdentityToken": "Token"} + + mockClient.EXPECT().ExternalPrincipalLoginWithResponse(gomock.Any(), gomock.Eq(externalLoginInfo)).Return( + &apiclient.ExternalPrincipalLoginResponse{ + HTTPResponse: &http.Response{ + StatusCode: http.StatusOK, + }, + JSON200: &apiclient.ExternalPrincipal{Id: principalId}, + }, nil) + + resp, err := s.ExternalPrincipalLogin(ctx, externalLoginInfo) + require.NoError(t, err) + require.Equal(t, principalId, resp.Id) +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 4386022b05e..630be306a98 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -190,12 +190,12 @@ type Config struct { AuthenticationAPI struct { // Endpoint for authentication operations Endpoint string `mapstructure:"endpoint"` + // ExternalPrincipalAuth configuration related external principals + ExternalPrincipalsEnabled bool `mapstructure:"external_principals_enabled"` } `mapstructure:"authentication_api"` RemoteAuthenticator struct { // Enabled if set true will enable remote authentication Enabled bool `mapstructure:"enabled"` - // ExternalPrincipalAuth configuration related external principals - ExternalPrincipalsEnabled bool `mapstructure:"external_principals_enabled"` // Endpoint URL of the remote authentication service (e.g. https://my-auth.example.com/auth) Endpoint string `mapstructure:"endpoint"` // DefaultUserGroup is the default group for the users authenticated by the remote service @@ -209,6 +209,7 @@ type Config struct { // server-side logout. LogoutRedirectURL string `mapstructure:"logout_redirect_url"` LoginDuration time.Duration `mapstructure:"login_duration"` + LoginMaxDuration time.Duration `mapstructure:"login_max_duration"` UIConfig struct { RBAC string `mapstructure:"rbac"` LoginURL string `mapstructure:"login_url"` @@ -541,7 +542,7 @@ func (c *Config) IsAuthTypeAPI() bool { func (c *Config) IsExternalPrincipalsEnabled() bool { // IsAuthTypeAPI must be true since the local auth service doesnt support external principals // ExternalPrincipalsEnabled indicates that the remote auth service enables external principals support since its optional extension - return c.IsAuthTypeAPI() && c.Auth.RemoteAuthenticator.ExternalPrincipalsEnabled + return c.IsAuthTypeAPI() && c.Auth.AuthenticationAPI.ExternalPrincipalsEnabled } func (c *Config) UISnippets() []apiparams.CodeSnippet { diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index d0c63b20643..60aea67f700 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -55,6 +55,7 @@ func setDefaults(cfgType string) { viper.SetDefault("auth.logout_redirect_url", "/auth/login") viper.SetDefault("auth.login_duration", 7*24*time.Hour) + viper.SetDefault("auth.login_max_duration", 14*24*time.Hour) viper.SetDefault("auth.ui_config.rbac", "simplified") viper.SetDefault("auth.ui_config.login_failed_message", "The credentials don't match.")