diff --git a/.github/workflows/ci-dotnet.yaml b/.github/workflows/ci-dotnet.yaml index ccdd822a..ae889517 100644 --- a/.github/workflows/ci-dotnet.yaml +++ b/.github/workflows/ci-dotnet.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/cs')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/cs')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/cs')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-dotnet: diff --git a/.github/workflows/ci-golang.yaml b/.github/workflows/ci-golang.yaml index 62639d92..c4a095e4 100644 --- a/.github/workflows/ci-golang.yaml +++ b/.github/workflows/ci-golang.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/go')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/go')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/go')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-golang: diff --git a/.github/workflows/ci-java-legacy.yaml b/.github/workflows/ci-java-legacy.yaml index bcb23f83..8ddef7e2 100644 --- a/.github/workflows/ci-java-legacy.yaml +++ b/.github/workflows/ci-java-legacy.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/java')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/java')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/java')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-java-legacy: diff --git a/.github/workflows/ci-java.yaml b/.github/workflows/ci-java.yaml index ba871452..8da06ace 100644 --- a/.github/workflows/ci-java.yaml +++ b/.github/workflows/ci-java.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/java')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/java')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/java')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-java: diff --git a/.github/workflows/ci-php.yaml b/.github/workflows/ci-php.yaml index beb06b4e..7392a9c7 100644 --- a/.github/workflows/ci-php.yaml +++ b/.github/workflows/ci-php.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-php: diff --git a/.github/workflows/ci-python.yaml b/.github/workflows/ci-python.yaml index 852e568b..a116b64c 100644 --- a/.github/workflows/ci-python.yaml +++ b/.github/workflows/ci-python.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/py')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/py')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/py')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-python: diff --git a/.github/workflows/ci-ruby.yaml b/.github/workflows/ci-ruby.yaml index f4a1788f..e8cb2780 100644 --- a/.github/workflows/ci-ruby.yaml +++ b/.github/workflows/ci-ruby.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/rb')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/rb')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/rb')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-ruby: diff --git a/.github/workflows/ci-rust.yaml b/.github/workflows/ci-rust.yaml index 5e3bcc9e..ee1f2674 100644 --- a/.github/workflows/ci-rust.yaml +++ b/.github/workflows/ci-rust.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/rs')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/rs')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/rs')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-rust: diff --git a/.github/workflows/ci-typescript.yaml b/.github/workflows/ci-typescript.yaml index 22b76229..0f361cb4 100644 --- a/.github/workflows/ci-typescript.yaml +++ b/.github/workflows/ci-typescript.yaml @@ -29,6 +29,9 @@ env: CLIENT_SECRET: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/ts')) && secrets.CLIENT_SECRET || secrets.STAGING_CLIENT_SECRET }} VAAS_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/ts')) && 'wss://gateway.production.vaas.gdatasecurity.de' || 'wss://gateway.staging.vaas.gdatasecurity.de' }} TOKEN_URL: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/ts')) && 'https://account.gdata.de/realms/vaas-production/protocol/openid-connect/token' || 'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token' }} + VAAS_CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }} + VAAS_USER_NAME: ${{ secrets.VAAS_USER_NAME }} + VAAS_PASSWORD: ${{ (inputs.environment == 'production' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/php')) && secrets.VAAS_PASSWORD || secrets.STAGING_VAAS_PASSWORD }} jobs: build-typescript: diff --git a/php/examples/VaasExample/AuthenticationExamples.php b/php/examples/VaasExample/AuthenticationExamples.php new file mode 100644 index 00000000..7e2e02af --- /dev/null +++ b/php/examples/VaasExample/AuthenticationExamples.php @@ -0,0 +1,50 @@ +Connect($authenticator->getToken()); +} catch (VaasAuthenticationException $e) { + fwrite(STDERR, "Authentication failed: " . $e->getMessage() . "\n"); + exit(1); +} + +// Get verdict for an eicar hash +try { + $vaasVerdict = $vaas->ForSha256("000005c43196142f01d615a67b7da8a53cb0172f8e9317a2ec9a0a39a1da6fe8"); +} catch (InvalidSha256Exception $e) { + fwrite(STDERR, "Invalid sha256: " . $e->getMessage() . "\n"); + exit(1); +} catch (TimeoutException $e) { + fwrite(STDERR, "Timeout: " . $e->getMessage() . "\n"); + exit(1); +} +fwrite(STDOUT, "Verdict for $vaasVerdict->Sha256 is $vaasVerdict->Verdict \n"); diff --git a/php/src/vaas/Message/Error.php b/php/src/vaas/Message/Error.php index c169cc1c..c94c33be 100644 --- a/php/src/vaas/Message/Error.php +++ b/php/src/vaas/Message/Error.php @@ -10,7 +10,7 @@ class Error public string $text; - public ProblemDetails $problem_details; + public ?ProblemDetails $problem_details; public Kind $kind; diff --git a/php/src/vaas/ResourceOwnerPasswordAuthenticator.php b/php/src/vaas/ResourceOwnerPasswordAuthenticator.php new file mode 100644 index 00000000..2c1089ed --- /dev/null +++ b/php/src/vaas/ResourceOwnerPasswordAuthenticator.php @@ -0,0 +1,46 @@ +clientId = $clientId; + $this->userName = $userName; + $this->password = $password; + $this->tokenEndpoint = $tokenEndpoint; + $this->verify = $verify; + } + + /** + * @throws VaasAuthenticationException + */ + public function getToken() { + $provider = new GenericProvider([ + 'clientId' => $this->clientId, + 'urlAuthorize' => $this->tokenEndpoint, + 'urlAccessToken' => $this->tokenEndpoint, + 'urlResourceOwnerDetails' => '', + 'verify' => $this->verify, + ]); + + try { + $accessToken = $provider->getAccessToken("password", [ + 'username' => $this->userName, + 'password' => $this->password + ]); + return $accessToken->getToken(); + } catch (IdentityProviderException $e) { + throw new VaasAuthenticationException($e->getMessage(), $e->getCode()); + } + } +} diff --git a/php/src/vaas/composer.json b/php/src/vaas/composer.json index 706e4acf..a93d52b0 100644 --- a/php/src/vaas/composer.json +++ b/php/src/vaas/composer.json @@ -18,7 +18,8 @@ "textalk/websocket": "^1.6 || ^1.5", "netresearch/jsonmapper": "^4.1", "guzzlehttp/guzzle": "^7", - "psr/log": "^1.1 || ^2.0 || ^3.0" + "psr/log": "^1.1 || ^2.0 || ^3.0", + "league/oauth2-client": "^2.4.0" }, "autoload": { "psr-4": { diff --git a/php/tests/vaas/VaasTest.php b/php/tests/vaas/VaasTest.php index e3c76c06..c8819e52 100644 --- a/php/tests/vaas/VaasTest.php +++ b/php/tests/vaas/VaasTest.php @@ -10,6 +10,7 @@ use VaasSdk\Exceptions\TimeoutException; use VaasSdk\Exceptions\VaasAuthenticationException; use VaasSdk\Exceptions\VaasClientException; +use VaasSdk\ResourceOwnerPasswordAuthenticator; use VaasSdk\Vaas; use Dotenv\Dotenv; use Monolog\Formatter\JsonFormatter; @@ -46,6 +47,15 @@ public function setUp(): void if (getenv("TOKEN_URL") !== false) { $_ENV["TOKEN_URL"] = getenv("TOKEN_URL"); } + if (getenv("VAAS_USER_NAME") !== false) { + $_ENV["VAAS_USER_NAME"] = getenv("VAAS_USER_NAME"); + } + if (getenv("VAAS_PASSWORD") !== false) { + $_ENV["VAAS_PASSWORD"] = getenv("VAAS_PASSWORD"); + } + if (getenv("VAAS_CLIENT_ID") !== false) { + $_ENV["VAAS_CLIENT_ID"] = getenv("VAAS_CLIENT_ID"); + } } private function _getDebugLogger(): LoggerInterface @@ -78,6 +88,29 @@ private function getClientCredentialsGrantAuthenticator(): ClientCredentialsGran ); } + private function getResourceOwnerPasswordAuthenticator(): ResourceOwnerPasswordAuthenticator + { + return new ResourceOwnerPasswordAuthenticator( + $_ENV['VAAS_CLIENT_ID'], + $_ENV['VAAS_USER_NAME'], + $_ENV["VAAS_PASSWORD"], + $_ENV["TOKEN_URL"] + ); + } + + public function testForSha256MaliciousSha256_WithResourceOwnerPasswordAuthenticator_GetsMaliciousResponse(): void + { + $uuid = $this->getUuid(); + + $vaas = new Vaas($_ENV["VAAS_URL"], $this->_getDebugLogger()); + $vaas->Connect($this->getResourceOwnerPasswordAuthenticator()->getToken()); + $verdict = $vaas->ForSha256(self::MALICIOUS_HASH, $uuid); + + $this->assertEquals(Verdict::MALICIOUS, $verdict->Verdict); + $this->assertEquals($uuid, $verdict->Guid); + $this->assertEqualsIgnoringCase(self::MALICIOUS_HASH, $verdict->Sha256); + } + public function testForConnectingWithInvalidToken_ThrowsVaasAccessDeniedException() { $this->expectException(VaasAuthenticationException::class); diff --git a/php/tests/vaas/composer.json b/php/tests/vaas/composer.json index c4f437c5..ea590a08 100644 --- a/php/tests/vaas/composer.json +++ b/php/tests/vaas/composer.json @@ -13,7 +13,8 @@ "require": { "gdata/vaas": "999", "vlucas/phpdotenv": "^5.5", - "monolog/monolog": "^3.3 || ^2.9" + "monolog/monolog": "^3.3 || ^2.9", + "league/oauth2-client": "^2.4.0" }, "require-dev": { "phpunit/phpunit": "^9",