From 7538b2c73f6882ce7c651b4b839d7b57ca03ecb4 Mon Sep 17 00:00:00 2001 From: sebprt Date: Wed, 26 Jun 2024 16:04:07 +0200 Subject: [PATCH] Added some composer authentication types --- src/Adapter/Composer.php | 57 ++++++++++++++++++ src/Adapter/Docker/Factory.php | 9 ++- src/Adapter/Docker/SatelliteBuilder.php | 65 +++++++++++++++++++- src/Adapter/Filesystem/Factory.php | 9 ++- src/Adapter/Filesystem/SatelliteBuilder.php | 67 ++++++++++++++++++++- src/Feature/Composer/Configuration.php | 54 ++++++++++++++++- 6 files changed, 253 insertions(+), 8 deletions(-) diff --git a/src/Adapter/Composer.php b/src/Adapter/Composer.php index 611c5de7..2fb2af99 100644 --- a/src/Adapter/Composer.php +++ b/src/Adapter/Composer.php @@ -219,4 +219,61 @@ public function addAuthenticationToken(string $url, string $token): void $token ); } + + public function addGitlabOauthAuthentication(string $token, string $url = 'gitlab.com'): void + { + $this->command( + 'composer', + 'config', + '--auth', + sprintf('gitlab-oauth.%s', $url), + 'token', + $token + ); + } + + public function addGitlabTokenAuthentication(string $token, string $url = 'gitlab.com'): void + { + $this->command( + 'composer', + 'config', + '--auth', + sprintf('gitlab-token.%s', $url), + $token + ); + } + + public function addGithubOauthAuthentication(string $token): void + { + $this->command( + 'composer', + 'config', + '--auth', + 'github-oauth.github.com', + $token + ); + } + + public function addHttpBasicAuthentication(string $url, string $username, string $password): void + { + $this->command( + 'composer', + 'config', + '--auth', + sprintf('http-basic.%s', $url), + $username, + $password, + ); + } + + public function addHttpBearerAuthentication(string $url, string $token): void + { + $this->command( + 'composer', + 'config', + '--auth', + sprintf('bearer.%s', $url), + $token + ); + } } diff --git a/src/Adapter/Docker/Factory.php b/src/Adapter/Docker/Factory.php index 5c47ae94..ca6e23ba 100644 --- a/src/Adapter/Docker/Factory.php +++ b/src/Adapter/Docker/Factory.php @@ -76,7 +76,14 @@ public function __invoke(array $configuration): Configurator\SatelliteBuilderInt if (\array_key_exists('auth', $configuration['composer']) && (is_countable($configuration['composer']['auth']) ? \count($configuration['composer']['auth']) : 0) > 0) { foreach ($configuration['composer']['auth'] as $auth) { - $builder->withComposerAuthenticationToken($auth['url'], $auth['token']); + match ($auth['type']) { + 'gitlab-oauth' => $builder->withGitlabOauthAuthentication($auth['token'], $auth['url'] ?? 'gitlab.com'), + 'gitlab-token' => $builder->withGitlabTokenAuthentication($auth['token'], $auth['url'] ?? 'gitlab.com'), + 'github-oauth' => $builder->withGithubOauthAuthentication($auth['token'], $auth['url'] ?? 'github.com'), + 'http-basic' => $builder->withHttpBasicAuthentication($auth['url'], $auth['username'], $auth['password']), + 'http-bearer' => $builder->withHttpBearerAuthentication($auth['url'], $auth['token']), + default => throw new \LogicException(), + }; } } } diff --git a/src/Adapter/Docker/SatelliteBuilder.php b/src/Adapter/Docker/SatelliteBuilder.php index 1ad2594c..59b35d71 100644 --- a/src/Adapter/Docker/SatelliteBuilder.php +++ b/src/Adapter/Docker/SatelliteBuilder.php @@ -132,6 +132,60 @@ public function withComposerAuthenticationToken(string $url, string $auth): self return $this; } + public function withGithubOauthAuthentication(string $token, string $url = 'github.com'): self + { + $this->authenticationTokens[$url] = [ + 'type' => 'github-token', + 'url' => $url, + 'token' => $token + ]; + + return $this; + } + + public function withGitlabOauthAuthentication(string $token, string $url = 'gitlab.com'): self + { + $this->authenticationTokens[$url] = [ + 'type' => 'gitlab-oauth', + 'url' => $url, + 'token' => $token + ]; + + return $this; + } + + public function withGitlabTokenAuthentication(string $token, string $url = 'gitlab.com'): self + { + $this->authenticationTokens[$url] = [ + 'type' => 'gitlab-token', + 'url' => $url, + 'token' => $token + ]; + + return $this; + } + + public function withHttpBasicAuthentication(string $url, string $username, string $password): self + { + $this->authenticationTokens[$url] = [ + 'type' => 'http-basic', + 'username' => $username, + 'password' => $password, + ]; + + return $this; + } + + public function withHttpBearerAuthentication(string $url, string $token): self + { + $this->authenticationTokens[$url] = [ + 'type' => 'http-bearer', + 'token' => $token + ]; + + return $this; + } + public function withTags(string ...$tags): self { $this->tags = $tags; @@ -201,8 +255,15 @@ public function build(): Configurator\SatelliteInterface } if (\count($this->authenticationTokens) > 0) { - foreach ($this->authenticationTokens as $url => $token) { - $dockerfile->push(new Dockerfile\PHP\ComposerAuthenticationToken($url, $token)); + foreach ($this->authenticationTokens as $url => $authentication) { + match ($authentication['type']) { + 'gitlab-oauth' => $dockerfile->push(new Dockerfile\PHP\ComposerGitlabOauthAuthentication($authentication['token'])), + 'gitlab-token' => $dockerfile->push(new Dockerfile\PHP\ComposerGitlabTokenAuthentication($authentication['token'])), + 'github-oauth' => $dockerfile->push(new Dockerfile\PHP\ComposerGithubOauthAuthentication($authentication['token'])), + 'http-basic' => $dockerfile->push(new Dockerfile\PHP\ComposerHttpBasicAuthentication($url, $authentication['username'], $authentication['password'])), + 'http-bearer' => $dockerfile->push(new Dockerfile\PHP\ComposerHttpBearerAuthentication($url, $authentication['token'])), + default => new \LogicException(), + }; } } diff --git a/src/Adapter/Filesystem/Factory.php b/src/Adapter/Filesystem/Factory.php index 31f63d5f..f1b2b8e1 100644 --- a/src/Adapter/Filesystem/Factory.php +++ b/src/Adapter/Filesystem/Factory.php @@ -58,7 +58,14 @@ public function __invoke(array $configuration): Configurator\SatelliteBuilderInt if (\array_key_exists('auth', $configuration['composer']) && (is_countable($configuration['composer']['auth']) ? \count($configuration['composer']['auth']) : 0) > 0) { foreach ($configuration['composer']['auth'] as $auth) { - $builder->withAuthenticationToken($auth['url'], $auth['token']); + match ($auth['type']) { + 'gitlab-oauth' => $builder->withGitlabOauthAuthentication($auth['token'], $auth['url'] ?? 'gitlab.com'), + 'gitlab-token' => $builder->withGitlabTokenAuthentication($auth['token'], $auth['url'] ?? 'gitlab.com'), + 'github-oauth' => $builder->withGithubOauthAuthentication($auth['token'], $auth['url'] ?? 'github.com'), + 'http-basic' => $builder->withHttpBasicAuthentication($auth['url'], $auth['username'], $auth['password']), + 'http-bearer' => $builder->withHttpBearerAuthentication($auth['url'], $auth['token']), + default => throw new \LogicException(), + }; } } } diff --git a/src/Adapter/Filesystem/SatelliteBuilder.php b/src/Adapter/Filesystem/SatelliteBuilder.php index 1a400c38..532bbf66 100644 --- a/src/Adapter/Filesystem/SatelliteBuilder.php +++ b/src/Adapter/Filesystem/SatelliteBuilder.php @@ -106,6 +106,62 @@ public function withAuthenticationToken(string $domain, string $auth): self return $this; } + public function withGitlabOauthAuthentication(string $token, string $domain = 'gitlab.com'): self + { + $this->authenticationTokens[$domain] = [ + 'type' => 'gitlab-oauth', + 'url' => $domain, + 'token' => $token, + ]; + + return $this; + } + + public function withGitlabTokenAuthentication(string $token, string $domain = 'gitlab.com'): self + { + $this->authenticationTokens[$domain] = [ + 'type' => 'gitlab-token', + 'url' => $domain, + 'token' => $token, + ]; + + return $this; + } + + public function withGithubOauthAuthentication(string $token, string $domain = 'github.com'): self + { + $this->authenticationTokens[$domain] = [ + 'type' => 'github-oauth', + 'url' => $domain, + 'token' => $token, + ]; + + return $this; + } + + public function withHttpBasicAuthentication(string $domain, string $username, string $password): self + { + $this->authenticationTokens[$domain] = [ + 'type' => 'http-basic', + 'url' => $domain, + 'username' => $username, + 'password' => $password, + ]; + + return $this; + } + + public function withHttpBearerAuthentication(string $domain, string $token): self + { + $this->authenticationTokens[$domain] = [ + 'type' => 'http-basic', + 'url' => $domain, + 'token' => $token, + ]; + + return $this; + } + public function build(): Configurator\SatelliteInterface { if (!file_exists($this->workdir)) { @@ -153,8 +209,15 @@ public function build(): Configurator\SatelliteInterface } if (\count($this->authenticationTokens) > 0) { - foreach ($this->authenticationTokens as $url => $token) { - $composer->addAuthenticationToken($url, $token); + foreach ($this->authenticationTokens as $url => $authentication) { + match ($authentication['type']) { + 'gitlab-oauth' => $composer->addGitlabOauthAuthentication($authentication['token']), + 'gitlab-token' => $composer->addGitlabTokenAuthentication($authentication['token']), + 'github-oauth' => $composer->addGithubOauthAuthentication($authentication['token']), + 'http-basic' => $composer->addHttpBasicAuthentication($url, $authentication['username'], $authentication['password']), + 'http-bearer' => $composer->addHttpBearerAuthentication($url, $authentication['token']), + default => $composer->addAuthenticationToken($url, $authentication['token']), + }; } } diff --git a/src/Feature/Composer/Configuration.php b/src/Feature/Composer/Configuration.php index 8d88c12d..61d3fefb 100644 --- a/src/Feature/Composer/Configuration.php +++ b/src/Feature/Composer/Configuration.php @@ -71,14 +71,64 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->arrayNode('auth') ->arrayPrototype() + ->beforeNormalization() + ->always(function ($value) { + if (isset($value['url']) && isset($value['token']) && !isset($value['type'])) { + $value['type'] = 'http-basic'; + $value['url'] = substr($value['url'], strpos($value['url'], 'http-basic.') + strlen('http-basic.')); + $value['username'] = $value['username'] ?? 'token'; + $value['password'] = $value['password'] ?? $value['token']; + unset($value['token']); + } + + return $value; + }) + ->end() + ->validate() + ->always(function ($v) { + switch ($v['type']) { + case 'http-basic': + if (empty($v['url']) || empty($v['username']) || empty($v['password'])) { + throw new \InvalidArgumentException('For http-basic auth, url, username, and password are required.'); + } + break; + case 'http-bearer': + if (empty($v['url']) || empty($v['token'])) { + throw new \InvalidArgumentException('For http-bearer auth, url and token are required.'); + } + break; + default: + if (empty($v['token'])) { + throw new \InvalidArgumentException('For gitlab-oauth, gitlab-token or github-oauth, only token is required and url is optional.'); + } + break; + } + return $v; + }) + ->end() ->children() - ->scalarNode('url')->isRequired()->end() + ->enumNode('type') + ->isRequired() + ->values(['http-basic', 'http-bearer', 'gitlab-oauth', 'gitlab-token', 'github-oauth']) + ->end() + ->scalarNode('url')->end() ->scalarNode('token') ->validate() ->ifTrue(isExpression()) ->then(asExpression()) ->end() - ->isRequired() + ->end() + ->scalarNode('username') + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() + ->end() + ->scalarNode('password') + ->validate() + ->ifTrue(isExpression()) + ->then(asExpression()) + ->end() ->end() ->end() ->end()