Symfony bundle providing common functionality for Keboola API applications.
Install the package with Composer:
composer require keboola/api-bundleThe bundle expects having %app_name% parameter defined in your Symfony configuration.
keboola_api:
app_name: '%app_name%' # application name to use in user agent
default_service_dns_type: public # default service DNS type to use in ServiceClient, can be 'public' or 'private'The bundle provides a preconfigured ServiceClient that can be used to resolve Keboola API URLs. By default, it is
configured to use public hostnames, but it can be reconfigured to use internal ones.
keboola_api:
default_service_dns_type: internalIf you need to use ENV variable to configure the default_service_dns_type, make sure you provide some default value,
otherwise the validation will fail with error The value "" is not allowed for path "keboola_api.default_service_dns_type".
parameters:
env(API_DNS_TYPE): internal
keboola_api:
default_service_dns_type: '%env(API_DNS_TYPE)%'To use authentication using attributes, configure firewall to use the keboola.api_bundle.security.attribute_authenticator:
security:
firewalls:
attribute:
lazy: true
stateless: true
custom_authenticators:
- keboola.api_bundle.security.attribute_authenticatorThen add any combination of authentication attributes to your controller:
use Keboola\ApiBundle\Attribute\StorageApiTokenAuth;
use Keboola\ApiBundle\Security\StorageApiToken\SecurityApiToken;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
#[StorageApiTokenAuth]
class Controller {
public function __invoke(#[CurrentUser] StorageApiToken $token)
{
// only requests with valid X-StorageApi-Token will be allowed
}
}
#[StorageApiTokenAuth(features: ['feat-a', 'feat-b'])]
class Controller {
public function __invoke(#[CurrentUser] StorageApiToken $token)
{
// only requests with valid X-StorageApi-Token and project features 'feat-a' AND 'feat-b' is allowed
}
}
#[StorageApiTokenAuth(features: ['feat-a'])]
#[StorageApiTokenAuth(features: ['feat-b'])]
class Controller {
public function __invoke(#[CurrentUser] StorageApiToken $token)
{
// only requests with valid X-StorageApi-Token and any of project features 'feat-a' OR 'feat-b' ise allowed
}
}
#[ApplicationTokenAuth(scopes: ['something:manage'])]
#[StorageApiTokenAuth]
class Controller {
public function __invoke(
string $entityId,
#[CurrentUser] TokenInterface $token,
) {
// allows request with a valid Manage API token (`X-KBC-ManageApiToken`) or a Kubernetes
// ServiceAccount JWT (`X-Kubernetes-Authorization: Bearer <jwt>`) with the 'something:manage'
// scope, OR any valid X-StorageApi-Token — but with additional checks in controller
$entity = $this->fetchEntity($entityId);
if ($token instanceof StorageApiToken && $token->getProjectId() !== $entity->getProjectId()) {
throw new AccessDeniedHttpException('...');
}
}
}ApplicationTokenAuth accepts both the Manage API token header (X-KBC-ManageApiToken)
and the Kubernetes ServiceAccount JWT header (X-Kubernetes-Authorization); Connection resolves
both to a Manage token, so scopes/isSuperAdmin checks are identical regardless of which header
the request carries.
To use individual authentication attributes, you need to install appropriate client package:
- to use
StorageApiTokenAuth, installkeboola/storage-api-client - to use
ApplicationTokenAuth, installkeboola/kbc-manage-api-php-client
Note
If you forget to install appropriate client, you will get exception like
Service "Keboola\ApiBundle\Attribute\ApplicationTokenAuth" not found: the container inside "Symfony\Component\DependencyInjection\Argument\ServiceLocator" is a smaller service locator
Keboola\ApiBundle\Test\AuthenticatorTestTrait stubs the authenticators in functional
(KernelTestCase) tests so guarded controllers can be exercised without reaching real
Storage/Manage APIs:
use Keboola\ApiBundle\Test\AuthenticatorTestTrait;
class MyActionTest extends KernelTestCase
{
use AuthenticatorTestTrait;
public function testIt(): void
{
// for #[StorageApiTokenAuth]
$token = $this->setupFakeStorageApiToken(projectId: '123', features: ['my-feature']);
// for #[ApplicationTokenAuth] — works for both the X-KBC-ManageApiToken
// header and the Kubernetes ServiceAccount JWT
$this->setupFakeManageApiToken('my-token', scopes: ['something:manage']);
}
}MIT licensed, see LICENSE file.