diff --git a/.github/workflows/build-golang-macos.yaml b/.github/workflows/build-golang-macos.yaml index 1c28348..626de1d 100644 --- a/.github/workflows/build-golang-macos.yaml +++ b/.github/workflows/build-golang-macos.yaml @@ -47,4 +47,4 @@ jobs: # - uses: ./.github/workflows/platform-integration-test.yaml # with: - # wheel: dist/otdf_python-0.2.13-py3-none-any.whl + # wheel: dist/otdf_python-0.2.14-py3-none-any.whl diff --git a/.github/workflows/build-golang-ubuntu.yaml b/.github/workflows/build-golang-ubuntu.yaml index a54555a..282a1d0 100644 --- a/.github/workflows/build-golang-ubuntu.yaml +++ b/.github/workflows/build-golang-ubuntu.yaml @@ -43,12 +43,12 @@ jobs: - uses: actions/cache/restore@v4 with: - path: dist/otdf_python-0.2.13-py3-none-any.whl + path: dist/otdf_python-0.2.14-py3-none-any.whl key: ${{ runner.os }}${{ matrix.python3_version }}-data-${{ github.sha }} - uses: actions/cache/save@v4 with: - path: dist/otdf_python-0.2.13-py3-none-any.whl + path: dist/otdf_python-0.2.14-py3-none-any.whl key: ${{ runner.os }}${{ matrix.python3_version }}-data-${{ github.sha }} restore-keys: | ${{ runner.os }}${{ matrix.python3_version }}-data- @@ -61,5 +61,5 @@ jobs: needs: build uses: ./.github/workflows/platform-integration-test.yaml with: - wheel: dist/otdf_python-0.2.13-py3-none-any.whl + wheel: dist/otdf_python-0.2.14-py3-none-any.whl python_version: ${{ matrix.python3_version }} diff --git a/.github/workflows/platform-integration-test.yaml b/.github/workflows/platform-integration-test.yaml index 6a4fb9b..b9aee0e 100644 --- a/.github/workflows/platform-integration-test.yaml +++ b/.github/workflows/platform-integration-test.yaml @@ -29,7 +29,7 @@ jobs: - uses: actions/cache/restore@v4 with: - path: dist/otdf_python-0.2.13-py3-none-any.whl + path: dist/otdf_python-0.2.14-py3-none-any.whl key: ${{ runner.os }}${{ inputs.python_version }}-data-${{ github.sha }} - name: Prove that the input file is available @@ -125,6 +125,7 @@ jobs: OPENTDF_HOSTNAME: "localhost:8080" OIDC_TOKEN_ENDPOINT: "http://localhost:8888/auth/realms/opentdf/protocol/openid-connect/token" OPENTDF_KAS_URL: "http://localhost:8080/kas" + INSECURE_SKIP_VERIFY: "TRUE" run: | mkdir validation wheel="$(basename ${{ inputs.wheel }} )" @@ -136,119 +137,7 @@ jobs: pip install ./"$wheel" python validate_otdf_python.py - # - name: Validate the SDK through the command line interface - # run: | - # printf 'here is some data to encrypt' > data - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # encrypt --kas-url=localhost:8080 --mime-type=text/plain --attr https://example.com/attr/attr1/value/value1 --autoconfigure=false -f data -m 'here is some metadata' > test.tdf - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # decrypt -f test.tdf > decrypted - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # metadata -f test.tdf > metadata - - # if ! diff -q data decrypted; then - # printf 'decrypted data is incorrect [%s]' "$(< decrypted)" - # exit 1 - # fi - - # if [ "$(< metadata)" != 'here is some metadata' ]; then - # printf 'metadata is incorrect [%s]\n' "$(< metadata)" - # exit 1 - # fi - # working-directory: cmdline - - # - name: Encrypt/Decrypt NanoTDF - # run: | - # echo 'here is some data to encrypt' > data - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # encryptnano --kas-url=http://localhost:8080 --attr https://example.com/attr/attr1/value/value1 -f data -m 'here is some metadata' > nano.ntdf - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # decryptnano -f nano.ntdf > decrypted - - # if ! diff -q data decrypted; then - # printf 'decrypted data is incorrect [%s]' "$(< decrypted)" - # exit 1 - # fi - # working-directory: cmdline - - # - uses: JarvusInnovations/background-action@2428e7b970a846423095c79d43f759abf979a635 - # name: start another KAS server in background - # with: - # run: > - # opentdf-beta.yaml yq e ' - # (.server.port = 8282) - # | (.mode = ["kas"]) - # | (.sdk_config = {"endpoint":"http://localhost:8080","plaintext":true,"client_id":"opentdf","client_secret":"secret"}) - # ' - # && go run ./service --config-file ./opentdf-beta.yaml start - # wait-on: | - # tcp:localhost:8282 - # log-output-if: true - # wait-for: 90s - # working-directory: platform - # - name: Make sure that the second platform is up - # run: | - # grpcurl -plaintext localhost:8282 kas.AccessService/PublicKey - # - name: Validate multikas through the command line interface - # run: | - # printf 'here is some data to encrypt' > data - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # encrypt --kas-url=localhost:8080,localhost:8282 -f data -m 'here is some metadata' > test.tdf - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # decrypt -f test.tdf > decrypted - - # java -jar target/cmdline.jar \ - # --client-id=opentdf-sdk \ - # --client-secret=secret \ - # --platform-endpoint=localhost:8080 \ - # -i \ - # metadata -f test.tdf > metadata - - # if ! diff -q data decrypted; then - # printf 'decrypted data is incorrect [%s]' "$(< decrypted)" - # exit 1 - # fi - # if [ "$(< metadata)" != 'here is some metadata' ]; then - # printf 'metadata is incorrect [%s]\n' "$(< metadata)" - # exit 1 - # fi - # working-directory: cmdline # platform-xtest: # permissions: diff --git a/README.md b/README.md index 2142e01..685ebc1 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,10 @@ Install from the [Python Package Index (PyPI)](https://pypi.org): pip install otdf_python # Install a pinned version -pip install otdf-python==0.2.13 +pip install otdf-python==0.2.14 # Install a pinned version, from test.pypi.org -pip install -i https://test.pypi.org/simple/ otdf-python==0.2.13 +pip install -i https://test.pypi.org/simple/ otdf-python==0.2.14 ``` ## Usage diff --git a/build-scripts/ci-build.sh b/build-scripts/ci-build.sh index 2d8982e..3263ff0 100755 --- a/build-scripts/ci-build.sh +++ b/build-scripts/ci-build.sh @@ -72,4 +72,4 @@ echo "✨✨✨ Build wheel" poetry run python3 setup.py bdist_wheel echo "✨✨✨ Install wheel" -pip install dist/otdf_python-0.2.13-py3-none-any.whl +pip install dist/otdf_python-0.2.14-py3-none-any.whl diff --git a/build-scripts/make_and_validate_script.sh b/build-scripts/make_and_validate_script.sh index 44230c0..2a232a2 100755 --- a/build-scripts/make_and_validate_script.sh +++ b/build-scripts/make_and_validate_script.sh @@ -47,7 +47,7 @@ python3 -m pip install --upgrade setuptools wheel python3 setup.py bdist_wheel # Prove that the wheel can be installed -pip install dist/otdf_python-0.2.13-py3-none-any.whl +pip install dist/otdf_python-0.2.14-py3-none-any.whl if [[ "$SKIP_TESTS" == "-s" || "$SKIP_TESTS" == "--skip-tests" ]]; then echo "Build is complete, skipping tests." diff --git a/build-scripts/uv_make_and_validate_script.sh b/build-scripts/uv_make_and_validate_script.sh index 3c6a18d..8263d37 100755 --- a/build-scripts/uv_make_and_validate_script.sh +++ b/build-scripts/uv_make_and_validate_script.sh @@ -70,7 +70,7 @@ loud_print "Installing wheel" uv venv .venv-wheel --python 3.12 "$PY_TYPE" source "${BUILD_ROOT}/.venv-wheel/bin/activate" pip install pybindgen -pip install dist/otdf_python-0.2.13-py3-none-any.whl +pip install dist/otdf_python-0.2.14-py3-none-any.whl if [[ "$SKIP_TESTS" == "-s" || "$SKIP_TESTS" == "--skip-tests" ]]; then echo "Build is complete, skipping tests." diff --git a/main.go b/main.go index b803362..cff45c3 100644 --- a/main.go +++ b/main.go @@ -42,26 +42,17 @@ type OpentdfConfig struct { KasUrl string } -/* -Based on: https://stackoverflow.com/a/42849112 -func inputValidation(normalConfig DecryptionConfig) (*DecryptionConfig, error) { - // Convert our Struct to a Map - var inInterface map[string]interface{} - inrec, _ := json.Marshal(normalConfig) - json.Unmarshal(inrec, &inInterface) - - // Iterate through fields in the map and fail if empty value found - for field, val := range inInterface { - if val == nil || val == "" { - // fmt.Println("KV Pair: ", field, val) - return nil, errors.New("Missing configuration value for field " + field) - } +func getEnv(key, defaultValue string) string { + if value, ok := os.LookupEnv(key); ok { + return value } - - return &normalConfig, nil + return defaultValue } -*/ +/* +NOTE: When the environment variable 'INSECURE_SKIP_VERIFY' is set to 'TRUE', +this option for the OpenTDF SDK will be set. +*/ func newSdkClient(config OpentdfConfig, authScopes []string) (*sdk.SDK, error) { // NOTE: The 'platformEndpoint' is sometimes referenced as 'host' if strings.Count(config.TokenEndpoint, "http://") == 1 { @@ -71,16 +62,25 @@ func newSdkClient(config OpentdfConfig, authScopes []string) (*sdk.SDK, error) { sdk.WithInsecurePlaintextConn(), ) } else if strings.Count(config.TokenEndpoint, "https://") == 1 { - return sdk.New(config.PlatformEndpoint, + opts := []sdk.Option{ sdk.WithClientCredentials(config.ClientId, config.ClientSecret, authScopes), sdk.WithTokenEndpoint(config.TokenEndpoint), - sdk.WithInsecureSkipVerifyConn(), - ) + } + + if getEnv("INSECURE_SKIP_VERIFY", "FALSE") == "TRUE" { + opts = append(opts, sdk.WithInsecureSkipVerifyConn()) + } + + return sdk.New(config.PlatformEndpoint, opts...) } else { return nil, errors.New("invalid TokenEndpoint given") } } +/* +NOTE: When the environment variable 'INSECURE_SKIP_VERIFY' is set to 'TRUE', +this option for the OpenTDF SDK will be set. +*/ func peSdkClient(config OpentdfConfig, authScopes []string, token TokenAuth) (*sdk.SDK, error) { // NOTE: The 'platformEndpoint' is sometimes referenced as 'host' if strings.Count(config.TokenEndpoint, "http://") == 1 { @@ -91,12 +91,17 @@ func peSdkClient(config OpentdfConfig, authScopes []string, token TokenAuth) (*s sdk.WithInsecurePlaintextConn(), ) } else if strings.Count(config.TokenEndpoint, "https://") == 1 { - return sdk.New(config.PlatformEndpoint, + opts := []sdk.Option{ sdk.WithClientCredentials(config.ClientId, config.ClientSecret, authScopes), sdk.WithTokenEndpoint(config.TokenEndpoint), sdk.WithTokenExchange(token.AccessToken, []string{token.NpeClientId}), - sdk.WithInsecureSkipVerifyConn(), - ) + } + + if getEnv("INSECURE_SKIP_VERIFY", "FALSE") == "TRUE" { + opts = append(opts, sdk.WithInsecureSkipVerifyConn()) + } + + return sdk.New(config.PlatformEndpoint, opts...) } else { return nil, errors.New("invalid TokenEndpoint given") } diff --git a/otdf_python_test.go b/otdf_python_test.go index 0df601b..009ac5c 100644 --- a/otdf_python_test.go +++ b/otdf_python_test.go @@ -1,11 +1,10 @@ -package gotdf_python_test +package gotdf_python import ( "crypto/tls" "encoding/json" "errors" "fmt" - "gotdf_python" "io" "log" "net/http" @@ -18,13 +17,6 @@ import ( var defaultAuthScopes = []string{"email"} -func getEnv(key, defaultValue string) string { - if value, ok := os.LookupEnv(key); ok { - return value - } - return defaultValue -} - type TestConfiguration struct { platformEndpoint string tokenEndpoint string @@ -67,7 +59,7 @@ A basic HTTP request Based on: https://stackoverflow.com/q/24493116 */ -func authHelper(form url.Values, isPEAuth bool) (gotdf_python.TokenAuth, error) { +func authHelper(form url.Values, isPEAuth bool) (TokenAuth, error) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } @@ -94,26 +86,26 @@ func authHelper(form url.Values, isPEAuth bool) (gotdf_python.TokenAuth, error) val, ok := jsonMap["access_token"].(string) // If the key exists if !ok { - return gotdf_python.TokenAuth{}, errors.New("Unable to obtain 'access_token', cannot continue") + return TokenAuth{}, errors.New("Unable to obtain 'access_token', cannot continue") } if isPEAuth { fmt.Println("Successfully auth'd PE", config.peUsername) - return gotdf_python.TokenAuth{ + return TokenAuth{ AccessToken: val, NpeClientId: config.npeClientId, }, nil } else { fmt.Println("Successfully auth'd NPE", config.npeClientId) - return gotdf_python.TokenAuth{ + return TokenAuth{ AccessToken: val, }, nil } } -func AuthenticatePE() (gotdf_python.TokenAuth, error) { +func AuthenticatePE() (TokenAuth, error) { form := url.Values{} form.Add("grant_type", "password") form.Add("client_id", config.npeClientId) @@ -123,7 +115,7 @@ func AuthenticatePE() (gotdf_python.TokenAuth, error) { return authHelper(form, true) } -func AuthenticateNPE() (gotdf_python.TokenAuth, error) { +func AuthenticateNPE() (TokenAuth, error) { form := url.Values{} form.Add("grant_type", "client_credentials") form.Add("client_id", config.npeClientId) @@ -140,7 +132,7 @@ func getMultiDataAttribute(config TestConfiguration) []string { func doEncryptString(t *testing.T, dataAttributes []string) { - got, err := gotdf_python.EncryptString("Hello, world", gotdf_python.OpentdfConfig{ + got, err := EncryptString("Hello, world", OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -205,7 +197,7 @@ func encrypt_file_NPE(t *testing.T, dataAttributes []string) string { } defer tmpOutputFile.Close() - got, err := gotdf_python.EncryptFile(tmpInputFile.Name(), tmpOutputFile.Name(), gotdf_python.OpentdfConfig{ + got, err := EncryptFile(tmpInputFile.Name(), tmpOutputFile.Name(), OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -228,7 +220,7 @@ func encrypt_file_NPE(t *testing.T, dataAttributes []string) string { return got } -func encrypt_file_PE(t *testing.T, dataAttributes []string, tokenAuth gotdf_python.TokenAuth) string { +func encrypt_file_PE(t *testing.T, dataAttributes []string, tokenAuth TokenAuth) string { tmpInputFile, err := os.CreateTemp("", "input-file-*.txt") if err != nil { log.Fatal("Could not create input file", err) @@ -251,7 +243,7 @@ func encrypt_file_PE(t *testing.T, dataAttributes []string, tokenAuth gotdf_pyth } defer tmpOutputFile.Close() - got, err := gotdf_python.EncryptFilePE(tmpInputFile.Name(), tmpOutputFile.Name(), gotdf_python.OpentdfConfig{ + got, err := EncryptFilePE(tmpInputFile.Name(), tmpOutputFile.Name(), OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -308,7 +300,7 @@ func e2e_test_as_PE(t *testing.T, dataAttributes []string) { if err != nil { t.Error(err) } - got, err := gotdf_python.DecryptFilePE(input_TDF_path, plaintext_output_path.Name(), gotdf_python.OpentdfConfig{ + got, err := DecryptFilePE(input_TDF_path, plaintext_output_path.Name(), OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -383,7 +375,7 @@ func Test_Multifile_NPE_Encrypt_Files_In_Dir_Nil_Attributes(t *testing.T) { t.Fatal("Unable to write to temporary file", err) } - cfg := gotdf_python.OpentdfConfig{ + cfg := OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -391,7 +383,7 @@ func Test_Multifile_NPE_Encrypt_Files_In_Dir_Nil_Attributes(t *testing.T) { KasUrl: config.kasEndpoint, } - got, err := gotdf_python.EncryptFilesWithExtensionsNPE(tmpDir, []string{".txt", ".csv"}, cfg, nil, defaultAuthScopes) + got, err := EncryptFilesWithExtensionsNPE(tmpDir, []string{".txt", ".csv"}, cfg, nil, defaultAuthScopes) if err != nil { t.Fatal("Failed to EncryptFilesWithExtensionsNPE()!", err) } @@ -416,7 +408,7 @@ func Test_Multifile_NPE_Encrypt_Files_With_Extensions_Nil_Attributes(t *testing. numFiles := createTestFiles(t, tmpDir) // Call the EncryptFilesWithExtensionsNPE function - got, err := gotdf_python.EncryptFilesWithExtensionsNPE(tmpDir, []string{".txt", ".csv", ".pdf"}, gotdf_python.OpentdfConfig{ + got, err := EncryptFilesWithExtensionsNPE(tmpDir, []string{".txt", ".csv", ".pdf"}, OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -447,7 +439,7 @@ func Test_Multifile_NPE_Decrypt_Files_In_Dir_Nil_Attributes(t *testing.T) { numFiles := createTestFiles(t, tmpDir) // Encrypt the file - _, err = gotdf_python.EncryptFilesInDirNPE(tmpDir, gotdf_python.OpentdfConfig{ + _, err = EncryptFilesInDirNPE(tmpDir, OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -459,7 +451,7 @@ func Test_Multifile_NPE_Decrypt_Files_In_Dir_Nil_Attributes(t *testing.T) { } // Call the DecryptFilesInDirNPE function - got, err := gotdf_python.DecryptFilesInDirNPE(tmpDir, gotdf_python.OpentdfConfig{ + got, err := DecryptFilesInDirNPE(tmpDir, OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -489,7 +481,7 @@ func Test_Multifile_NPE_Decrypt_Files_With_Extensions_Nil_Attributes(t *testing. numFiles := createTestFiles(t, tmpDir) // Encrypt the files - _, err = gotdf_python.EncryptFilesWithExtensionsNPE(tmpDir, []string{".txt", ".csv", ".pdf"}, gotdf_python.OpentdfConfig{ + _, err = EncryptFilesWithExtensionsNPE(tmpDir, []string{".txt", ".csv", ".pdf"}, OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, @@ -501,7 +493,7 @@ func Test_Multifile_NPE_Decrypt_Files_With_Extensions_Nil_Attributes(t *testing. } // Call the DecryptFilesWithExtensionsNPE function - got, err := gotdf_python.DecryptFilesWithExtensionsNPE(tmpDir, []string{".tdf"}, gotdf_python.OpentdfConfig{ + got, err := DecryptFilesWithExtensionsNPE(tmpDir, []string{".tdf"}, OpentdfConfig{ ClientId: config.npeClientId, ClientSecret: config.npeClientSecret, PlatformEndpoint: config.platformEndpoint, diff --git a/pyproject.toml b/pyproject.toml index 72b6df2..ecb63a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "otdf-python" # Should match 'setup.py' version number (used for gopy/pybindgen) -version = "0.2.13" +version = "0.2.14" description = "Unofficial OpenTDF SDK for Python." authors = [ {name="b-long", email="b-long@users.noreply.github.com"} @@ -19,7 +19,7 @@ pybindgen = "^0.22.1" [tool.poetry] package-mode = false -version = "0.2.13" +version = "0.2.14" [tool.poetry.dependencies] python = ">=3.11,<3.14" diff --git a/setup.py b/setup.py index d9b0063..5015a6d 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ url="https://github.com/b-long/opentdf-python-sdk", package_data={"otdf_python": ["*.so"]}, # Should match 'pyproject.toml' version number - version="0.2.13", + version="0.2.14", author_email="b-long@users.noreply.github.com", include_package_data=True, ) diff --git a/setup_ci.py b/setup_ci.py index ac6fec6..3ad6da4 100644 --- a/setup_ci.py +++ b/setup_ci.py @@ -81,7 +81,7 @@ def build_extension(self, ext: Extension): setuptools.setup( name="otdf_python", - version="0.2.13", + version="0.2.14", author="b-long", description="Unofficial OpenTDF SDK for Python.", long_description_content_type="text/markdown", diff --git a/uv.lock b/uv.lock index edd153b..7385017 100644 --- a/uv.lock +++ b/uv.lock @@ -3,5 +3,5 @@ requires-python = ">=3.11" [[package]] name = "otdf-python" -version = "0.2.13" +version = "0.2.14" source = { editable = "." }